You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WiX安装程序将ASP.NET Core应用注册为Windows服务时遇错误排查

WiX安装程序将ASP.NET Core应用注册为Windows服务时遇错误排查

我正在尝试让我的WiX安装程序在安装过程中将ASP.NET Core应用注册为Windows服务。

这是我的program.wsx中的部分代码:

<Fragment>
    <Component Id="WindowsServiceComponent" Guid="B1234567-89AB-CDEF-0123-456789ABCDEF" Directory="INSTALLFOLDER">
        <File Id="MyServiceExe" Source="C:\Navcon\net8.0\win-x64\NAV.LocalService.Function.exe" KeyPath="yes"/>

    <!-- Register as Windows Service -->
    <ServiceInstall
        Id="MyAspNetCoreServiceInstall"
        Name="Nav.LocalService"
        DisplayName="My ASP.NET Core Service"
        Description="Runs the ASP.NET Core Web API as a Windows Service"
        Start="auto"
        Type="ownProcess"
        ErrorControl="ignore"
        Account="NT AUTHORITY\NetworkService"
    />

    <!-- Ensure service starts after installation -->
    <ServiceControl
        Id="MyAspNetCoreServiceControl"
        Name="Nav.LocalService"
        Start="install"
        Stop="both"
        Remove="uninstall"
        Wait="yes"
    />
</Component>

但在安装过程中,我遇到了这个错误:
安装错误提示

当然,安装过程中确实会询问我是否要以管理员权限运行,我也点击了“以管理员身份运行”,但这似乎没有帮助。

有没有人知道可能哪里出问题了?

这是我的program.cs代码:

var builder = WebApplication.CreateBuilder(args);
int freePort = 0; 

// Load default settings
builder.Configuration
    .AddJsonFile("local.settings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables();

builder.Host.UseWindowsService(options =>
{
    options.ServiceName = "Nav.LocalService"; // MUST MATCH WiX ServiceInstall Name
});

// Determine user-specific settings file path in AppData
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var userSettingsFilePath = Path.Combine(appDataPath, "LocalService", "local.settings.json");

if (File.Exists(userSettingsFilePath))
{
    // if we have a local file for each user, take this instead and leave the other one as backup
    builder.Configuration.AddJsonFile(userSettingsFilePath, optional: true, reloadOnChange: true);
}
else
{
    // copy local file if it doenst already exist

    // Ensure the directory exists
    var directoryPath = Path.GetDirectoryName(userSettingsFilePath);
    if (!Directory.Exists(directoryPath))
    {
        Directory.CreateDirectory(directoryPath);
    }
    var sourceFilePath = Path.Combine(Directory.GetCurrentDirectory(), "local.settings.json");

    var fileContent = File.ReadAllText(sourceFilePath); // Read the content of the existing file

    File.WriteAllText(userSettingsFilePath, fileContent);

    builder.Configuration.AddJsonFile(userSettingsFilePath, optional: true, reloadOnChange: true);

    Thread.Sleep(100);
}

var getLastUsedPort = builder.Configuration["Values:Application:FunctionAppPort"];

builder.Services
    .AddHttpClient()
    .AddTransient<NTLMRegisterSender>()
    .AddTransient<PrintDocumentAction>()
    .AddTransient<OpenDocumentAction>()
    .AddTransient<SaveDocumentAction>()
    .AddSingleton<LoginStateModel>()
    .AddTransient<RegisterController>()
    .AddSingleton<NtlmRequestSenderService>()
    .AddHostedService<NtlmRequestSenderService>()
    .AddHostedService<EndpointTriggerService>()
    .AddControllers();

var app = builder.Build();

if (String.IsNullOrEmpty(getLastUsedPort))
{
    // no old port available get a new one
    freePort = Converters.GetFreePort();
    var updater = new ConfigUpdater();
    updater.UpdateConfig("Application:FunctionAppPort", freePort.ToString());
}
else
{
    // we had a port already, check if its free
    var portStillFree = Converters.IsPortAvailable(int.Parse(getLastUsedPort));

    if (!portStillFree)
    {
        // port is no longer free, retrieve new one, write to config and update on BC
        freePort = Converters.GetFreePort();
        var updater = new ConfigUpdater();
        updater.UpdateConfig("Application:FunctionAppPort", freePort.ToString());

        //Update new port on BC 
        using (var scope = app.Services.CreateScope())
        {
            var ntlmRegisterSender = scope.ServiceProvider.GetRequiredService<NTLMRegisterSender>();
            await ntlmRegisterSender.UpdateFieldValue("Port", freePort.ToString());
        }
    }
    else
    {
        // do nothing, leave everythign as it is 
    }
}

var logger = app.Services.GetRequiredService<ILogger<Program>>();

// Hide the console window
HideConsoleWindow();

app.UseRouting();
app.MapControllers();

Thread.Sleep(1000);

string uripath = builder.Configuration["Values:Application:FunctionAppUrl"] ?? "http://localhost:";

uripath += builder.Configuration["Values:Application:FunctionAppPort"] ?? "7072";

string trayAppPath = Converters.GetPathToWPFApp(builder.Configuration["TrayAppPath"]);

try
{
    Process.Start(trayAppPath, uripath);
    logger.LogInformation("Successfully started the tray app.");
}
catch (Exception ex)
{
    logger.LogWarning(ex, "Could not start the tray app. Check local.settings.json for the correct path.");
}

try
{
    app.Run(uripath);
}
catch (Exception ex)
{
    Console.WriteLine($"Failed to start server: {ex.Message}");
}

void HideConsoleWindow()
{
    IntPtr handle = GetConsoleWindow();

    if (handle != IntPtr.Zero)
    {
        ShowWindow(handle, 0);
    }
}

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

备注:内容来源于stack exchange,提问作者innom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:59:34