netcore开发windows普通服务(非Web)并一键发布到服务器
netcore下開發windows服務如果是web項目的話,由于aspnetcore本身是支持的,把默認的host.Run改為host.RunAsService就可以了。
但是普通的netcore的控制臺項目我終于找到了如下方式來實現:
Microsoft.Extensions.Hosting
System.ServiceProcess.ServiceController
{
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單獨使用的一個開源工具)
開源地址: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
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的netcore开发windows普通服务(非Web)并一键发布到服务器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NetCore使用skywalking
- 下一篇: 直播预告 - 微软MVP为你揭秘Visu