我有一个 Windows 窗体应用程序,可以及时调用 Web 服务。我将其作为 Windows 窗体进行,因为跟踪通信和测试更简单。 但现在我需要它作为 Windows 服务运行,这样它就可以安装在 Windows 服务器中并在无人值守的情况下运行。 我见过的样本都是从工人服务项目开始的。但我想让我的 Windows 窗体应用程序作为服务运行。
使用.NET 4.5,我成功构建了一个像这样的服务启动项目:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new CRDService()
};
ServiceBase.Run(ServicesToRun);
}
}
还有像这样的服务加载器:
public partial class CRDService : ServiceBase
{
private int processId;
private string filePath;
public CRDService()
{
InitializeComponent();
}
public void Verify(string[] args)
{
this.OnStart(args);
// do something here...
this.OnStop();
}
protected override void OnStart(string[] args)
{
var location = new Uri(Assembly.GetEntryAssembly().CodeBase).LocalPath;
var path = Path.GetDirectoryName(location);
string appName = ConfigurationManager.AppSettings["AppName"];
var serverPath = Path.Combine(path, appName);
Process cmd = new Process();
cmd.StartInfo.FileName = serverPath;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
using (var f = File.Create(Path.Combine(path, "TestFile.txt")))
{
filePath = f.Name;
string msg = "Process started at " + DateTime.Now.ToString();
f.Write(Encoding.ASCII.GetBytes(msg),0,msg.Length);
}
cmd.StartInfo.Arguments = filePath;
cmd.Start();
processId = cmd.Id;
}
protected override void OnStop()
{
Process process = null;
try
{
process = Process.GetProcessById((int)processId);
}
finally
{
if (process != null)
{
process.Kill();
process.WaitForExit();
process.Dispose();
}
File.Delete(filePath);
}
}
}
但这不适用于.NET 6 和BackgroundService。
有人可以告诉我是否有办法在 .NET 6/7 中做到这一点?
设法解决问题。 这是 .NET 6/7 的相同解决方案。
using GatewayATService;
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "GatewayAT Service";
})
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly Task _completedTask = Task.CompletedTask;
private int processId;
private string filePath;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("GatewayAT Service is starting.");
var location = new Uri(System.AppDomain.CurrentDomain.BaseDirectory).LocalPath;
var path = Path.GetDirectoryName(location);
//string appName = ConfigurationManager.AppSettings["AppName"];
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
IConfiguration config = builder.Build();
string appName = config.GetValue<string>("AppName");
var serverPath = Path.Combine(path, appName);
Process cmd = new Process();
cmd.StartInfo.FileName = serverPath;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
using (var f = File.Create(Path.Combine(path, "log.txt")))
{
filePath = f.Name;
string msg = "Process started at " + DateTime.Now.ToString();
f.Write(Encoding.ASCII.GetBytes(msg), 0, msg.Length);
}
cmd.StartInfo.Arguments = filePath;
cmd.Start();
processId = cmd.Id;
return _completedTask;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("GatewayAT Service is stopping.");
Process process = null;
try
{
process = Process.GetProcessById((int)processId);
}
finally
{
if (process != null)
{
process.Kill();
process.WaitForExit();
process.Dispose();
}
File.Delete(filePath);
}
return _completedTask;
}
}
``
`