netcore下開發windows服務若是是web項目的話,因爲aspnetcore自己是支持的,把默認的host.Run改成host.RunAsService就能夠了。git
可是普通的netcore的控制檯項目我終於找到了以下方式來實現:github
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<IHostLifetime, ServiceBaseLifetime>()); } 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<TestService>(); }); if (isService) { await builder.RunAsServiceAsync(); } else { await builder.RunConsoleAsync(); } } }
AntDeploy是我開發的一款開源一鍵部署vs插件(也是支持脫離vs單獨使用的一個開源工具)web
開源地址:https://github.com/yuzd/AntDeployAgentwindows
注意:Token不是windows服務器的密碼!!!是安裝agent後,agent的配置文件裏面配置的Token(你本身自定義配置的)
注意:Port不是你要發佈的項目的端口號!!!是安裝agent後,agent的配置文件裏面配置的端口號(你本身自定義配置的)
點擊【Connect Test】按鈕進行確認agent能夠成功連接,不然會發布失敗
若是【Connect Fail】失敗 請查看 #10服務器
Sdk類型選擇 netcore
ServiceName 填寫上面咱們設置的名稱:[TestService]app
點擊 【Deploy】按鈕進行發佈async
確認服務器無誤 點擊 【是】開始執行一鍵部署
若是發佈出現錯誤會出現下圖所示:ide
能夠在Log裏面查看失敗緣由是由於我部署agent沒有用管路員權限 報權限不足失敗 須要用管理員權限運行agent才行工具
部署成功 以下圖:測試
查看D盤下是否log.txt是否正常每隔1秒寫入了當前時間
這裏演示的是windows服務上沒有這個service因此自動建立了。若是service已存在的狀況 Deploy 就會全量覆蓋 不會從新建立site的。若是想要覆蓋時排除指定文件 能夠在 Setting Tab界面的IgnoreList裏面增長(支持正則)