netcore下開發windows服務如果是web專案的話,由於aspnetcore本身是支援的,把預設的host.Run改為host.RunAsService就可以了。
但是普通的netcore的控制檯專案我終於找到瞭如下方式來實現:
- Microsoft.Extensions.Hosting
- System.ServiceProcess.ServiceController
public class ServiceBaseLifetime : ServiceBase, IHostLifetime { private readonly TaskCompletionSource _delayStart = new TaskCompletionSource(); public ServiceBaseLifetime(IApplicationLifetime applicationLifetime) { ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime)); } private IApplicationLifetime ApplicationLifetime { get; } public Task WaitForStartAsync(CancellationToken cancellationToken) { cancellationToken.Register(() => _delayStart.TrySetCanceled()); ApplicationLifetime.ApplicationStopping.Register(Stop); new Thread(Run).Start(); // Otherwise this would block and prevent IHost.StartAsync from finishing. return _delayStart.Task; } private void Run() { try { Run(this); // This blocks until the service is stopped. _delayStart.TrySetException(new InvalidOperationException("Stopped without starting")); } catch (Exception ex) { _delayStart.TrySetException(ex); } } public Task StopAsync(CancellationToken cancellationToken) { Stop(); return Task.CompletedTask; } // Called by base.Run when the service is ready to start. protected override void OnStart(string[] args) { _delayStart.TrySetResult(null); base.OnStart(args); } // Called by base.Stop. This may be called multiple times by service Stop, ApplicationStopping, and StopAsync. // That's OK because StopApplication uses a CancellationTokenSource and prevents any recursion. protected override void OnStop() { ApplicationLifetime.StopApplication(); base.OnStop(); } }
public static class ServiceBaseLifetimeHostExtensions { public static IHostBuilder UseServiceBaseLifetime(this IHostBuilder hostBuilder) { return hostBuilder.ConfigureServices((hostContext, services) => services.AddSingleton()); } public static void RunAsService(this IHostBuilder hostBuilder) { hostBuilder.UseServiceBaseLifetime().Build().Run(); } public static Task RunAsServiceAsync(this IHostBuilder hostBuilder) { return hostBuilder.UseServiceBaseLifetime().Build().RunAsync(CancellationToken.None); } }
public class TestService: IHostedService,IDisposable { readonly System.Timers.Timer tmBak = new System.Timers.Timer(); public TestService() { tmBak.Interval = 1000;//1秒執行1次 tmBak.AutoReset = true;//執行1次false,一直執行true tmBak.Enabled = true; tmBak.Elapsed += (sender, eventArgs) => { using (StreamWriter sw = new StreamWriter("D:\\log.txt",true)) { sw.WriteLine($"AntDeploy Windows服務:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); } }; } public Task StartAsync(CancellationToken cancellationToken) { tmBak.Start(); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { tmBak.Stop(); return Task.CompletedTask; } public void Dispose() { this.tmBak.Dispose(); } }
class Program { // P/Invoke declarations for Windows. [DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr hWnd); public static bool HaveVisibleConsole() { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? IsWindowVisible(GetConsoleWindow()) : Console.WindowHeight > 0; } private static async Task Main(string[] args) { var pathToExe = Process.GetCurrentProcess().MainModule.FileName; var pathToContentRoot = Path.GetDirectoryName(pathToExe); Directory.SetCurrentDirectory(pathToContentRoot); var isService = !(Debugger.IsAttached || args.Contains("--console")); if (HaveVisibleConsole()) isService = false; var builder = new HostBuilder() .ConfigureServices((hostContext, services) => { services.AddHostedService(); }); if (isService) { await builder.RunAsServiceAsync(); } else { await builder.RunConsoleAsync(); } } }
AntDeploy是我開發的一款開源一鍵部署vs外掛(也是支援脫離vs單獨使用的一個開源工具)
開源地址:https://github.com/yuzd/AntDeployAgent
新增一個環境 名字叫 測試 然後 在 測試環境裡面新增 windows伺服器 這裡我做測試就新增就是我本機,註意Host裡面是填寫格式為:ip:埠號
註意:Token不是windows伺服器的密碼!!!是安裝agent後,agent的配置檔案裡面配置的Token(你自己自定義配置的)
註意:Port不是你要釋出的專案的埠號!!!是安裝agent後,agent的配置檔案裡面配置的埠號(你自己自定義配置的)
點選【Connect Test】按鈕進行確認agent可以成功連結,否則會釋出失敗
如果【Connect Fail】失敗 請檢視 #10
進入 WindowsService Tab介面
Sdk型別選擇 netcore
ServiceName 填寫上面我們設定的名稱:[TestService]
點選 【Deploy】按鈕進行釋出
確認伺服器無誤 點選 【是】開始執行一鍵部署
如果釋出出現錯誤會出現下圖所示:
可以在Log裡面檢視失敗原因是因為我部署agent沒有用管路員許可權 報許可權不足失敗 需要用管理員許可權執行agent才行
部署成功 如下圖:
檢視D盤下是否log.txt是否正常每隔1秒寫入了當前時間
這裡演示的是windows服務上沒有這個service
所以自動建立了。
如果service已存在的情況 Deploy 就會全量改寫 不會重新建立site的。
如果想要改寫時排除指定檔案 可以在 Setting Tab介面的IgnoreList裡面增加(支援正則)
原文地址:https://www.cnblogs.com/yudongdong/p/10630835.html