用sc. 启动c#服务



我正在c# visual studio中使用worker service模板为windows和macos编写一个小的自包含服务。

它使用相同的代码库,因此在Program.cs

中检查。我已经写了这个服务,它可以在windows上运行,当从visual studio中启动时。

我已经用

发布了它
dotnet publish .WorkerServiceTest2 -c Release -r win-x64 -- self-contained true /p:PublishSingleFile=true /p:PublishedTrimmed=true

并尝试使用

安装它
runas /user:MYUSERNAME "sc.exe create WorkerServiceTest2 c:UsersMYYUSERNAMEDocumentsblablablaWorkerServiceTest2.exe"

但是它没有显示在服务列表中,并且

sc.exe start WorkerServiceTest2 

表示此服务未安装。

是否有任何地方我可以看到如何sc.exe创建出来?或者也许有人能看到我做错了什么?

衷心谢谢

My Service Program.cs是这样的

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Runtime.InteropServices;
namespace WorkerServiceTest2
{
public class Program
{
public static void Main(string[] args)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)){
Console.WriteLine("WinOS");
CreateHostBuilderWin(args).Build().Run(); 
} else
{
Console.WriteLine("MacOS");
CreateHostBuilderMac(args).Build().Run();
}
}
private static void configureServices(HostBuilderContext context, IServiceCollection services)
{
services.AddHostedService<Worker>();
}
public static IHostBuilder CreateHostBuilderWin(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
public static IHostBuilder CreateHostBuilderMac(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(configureServices);
}
}

My Worker.cs是这样的

using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
using WorkerServiceTest2.SocketService;
namespace WorkerServiceTest2
{
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//Her skal business logic være.
SocketServer socketServer = new SocketServer();
await socketServer.start();
}
}
}
}

这是一个您可以使用的脚本。它将检查服务是否已安装。如果它已经存在,它将卸载它并安装新的。将其保存为MyScript.ps1(或您自己的偏好),并运行如下命令:

.MyScript.ps1 -serviceName name_of_service -serviceUsername some_username -servicePassword some_password -binaryPath "C:yourProgram.exe"

脚本:

# Sample: howto run ps-script from power-shell:
#.Install-WindowsService_v3.ps1 -serviceName aTestservice -serviceUsername some_username -servicePassword some_password -binaryPath "C:yourProgram.exe"
param
(
[string]$serviceName,
[string]$serviceUsername,
[string]$servicePassword,
[string]$binaryPath,
[string]$startupType='Automatic',
[string]$dependsOn
)
$secpasswd = ConvertTo-SecureString  $servicePassword -AsPlainText -Force
Write-Output "########################################"
Write-Output "Starting installation of windows service."
Write-Output "[serviceName] = $serviceName"
Write-Output "[serviceUsername] = $serviceUsername" -verbose
Write-Output "[binaryPath] = $binaryPath"
#Check Parameters
if (!$binaryPath) { throw "[binaryPath] parameter missing" }
if ((Test-Path $binaryPath)-eq $false)
{
Write-Output "Path doesn't exist: $binaryPath"
Write-Output "Service will not be installed."
throw [System.IO.FileNotFoundException] "$binaryPath doesn't exist."
}
# verify if the service already exists, and if yes remove it first
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
Stop-Service -Name $serviceName
# using WMI to remove Windows service because PowerShell does not have CmdLet for this
$serviceToRemove = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
$serviceToRemove.delete()
Write-Output "Service $serviceName was stopped and uninstalled."
}
else
{
Write-Output "Service didn't exist on the server"
}

if ($startupType -eq "AutomaticDelayedStart" ) 
{ 
$startupType = "Automatic"
$enableDelayed = "true" 
}

Write-Output "Installing service"
# creating credentials which can be used to run my windows service
$mycreds = New-Object System.Management.Automation.PSCredential ($serviceUsername, $secpasswd)
# creating windows service using all provided parameters
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType $startupType -credential $mycreds -DependsOn $dependsOn

# Set "automatic delayed" after service was installed, since it is not a valid argument when using "New-Service"
if ($enableDelayed -eq "true" ) 
{   
$command = "sc.exe config $serviceName start= delayed-auto"
$Output = Invoke-Expression -Command $Command -ErrorAction Stop
if($LASTEXITCODE -ne 0){
Write-Host "$Computer : Failed to set $serviceName to delayed start. 
More details: $Output" -foregroundcolor red
$failedcomputers +=$ComputerName
} else {
Write-Host "$Computer : Successfully changed $serviceName  
to delayed start" -foregroundcolor green
$successcomputers +=$ComputerName
}
}
# verify if the service exists after installation
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
Write-Output "Installation complete."
}
else
{
throw "Installation failed."
} 
Write-Output "########################################"

同样,在我所有的应用程序中,我像这样启动它们:

static async Task Main(string[] args)
{
isService = !(Debugger.IsAttached || args.Contains("--console"));
IWebHost host = CreateWebHostBuilder(args).Build();
if (isService)
{
var hostService = new MyCustomWebService(host);
ServiceBase.Run(hostService);
}
else
{
await host.RunAsync();
}
}

public class MyCustomWebService: WebHostService
{
private ILogger<MyCustomWebService> logger;
public MyCustomWebService(IWebHost host) : base(host)
{
var loggerFactory = host.Services.GetService<ILoggerFactory>();
logger = loggerFactory.CreateLogger<MyCustomWebService>();
logger.LogInformation("Starting...");
}
protected override void OnStopped()
{
logger.LogInformation("Will stop now.");
base.OnStopped();
}
}

需要Microsoft.AspNetCore.Hosting.WindowsServices

进一步推荐阅读:https://learn.microsoft.com/en us/aspnet/core/host -和- deploy/windows service?view=aspnetcore - 5.0,标签= visual studio

https://learn.microsoft.com/en us/dotnet/api/microsoft.aspnetcore.hosting.windowsservices?view=aspnetcore - 5.0

最新更新