尝试在 .NET 7 Windows 服务中复制阻止停止命令的行为。 当我阅读 Topshelf 代码时,他们的服务主机正在对
ServiceBase
进行子类化,并且在 OnStop
覆盖中,如果 _serviceHandle.Stop(this)
返回 false
,它会抛出异常。 这会设置 ExitCode = 1064
并重新抛出。
public class WindowsServiceHost :
ServiceBase,
Host,
HostControl
{
// omitted for brevity
protected override void OnStop()
{
try
{
_log.Info("[Topshelf] Stopping");
if (!_serviceHandle.Stop(this))
throw new TopshelfException("The service did not stop successfully (return false).");
_log.Info("[Topshelf] Stopped");
}
catch (Exception ex)
{
_settings.ExceptionCallback?.Invoke(ex);
_log.Fatal("The service did not shut down gracefully", ex);
ExitCode = (int) TopshelfExitCode.ServiceControlRequestFailed;
throw;
}
}
ServiceBase
代码,它只是调用OnStop
,如果抛出异常,只需将服务状态重新设置为“上一个”(正在运行)并重新抛出即可。
private unsafe void DeferredStop ()
{
fixed (NativeMethods.SERVICE_STATUS *pStatus = &status)
{
int previousState = status.currentState;
status.checkPoint = 0;
status.waitHint = 0;
status.currentState = NativeMethods.STATE_STOP_PENDING;
NativeMethods.SetServiceStatus (statusHandle, pStatus);
try
{
OnStop();
// omitted for brevity...
}
catch (Exception e)
{
status.currentState = previousState;
NativeMethods.SetServiceStatus (statusHandle, pStatus);
WriteEventLogEntry (Res.GetString (Res.StopFailed, e.ToString ()), EventLogEntryType.Error);
throw;
}
} // fixed
} // DeferredStop
我已经使用以下“相同”代码为 .NET 7 派生自
WindowsServiceLifetime
(其本身派生于 ServiceBase
)创建了自己的类,但在我在 OnStop
中抛出异常后,服务确实 停止了。
[System.Runtime.Versioning.SupportedOSPlatform( "windows" )]
public class CancelableWindowsServiceLifetime : Microsoft.Extensions.Hosting.WindowsServices.WindowsServiceLifetime
{
private readonly ICancelableBackgroundService cancelableBackgroundService;
public CancelableWindowsServiceLifetime( IHostEnvironment environment, IHostApplicationLifetime applicationLifetime, ICancelableBackgroundService cancelableBackgroundService, ILoggerFactory loggerFactory, IOptions<HostOptions> optionsAccessor )
: this( environment, applicationLifetime, cancelableBackgroundService, loggerFactory, optionsAccessor, Options.Create( new WindowsServiceLifetimeOptions() ) )
{
}
public CancelableWindowsServiceLifetime( IHostEnvironment environment, IHostApplicationLifetime applicationLifetime, ICancelableBackgroundService cancelableBackgroundService, ILoggerFactory loggerFactory, IOptions<HostOptions> optionsAccessor, IOptions<WindowsServiceLifetimeOptions> windowsServiceOptionsAccessor )
: base( environment, applicationLifetime, loggerFactory, optionsAccessor, windowsServiceOptionsAccessor )
{
this.cancelableBackgroundService = cancelableBackgroundService;
}
protected override void OnStop()
{
if ( !cancelableBackgroundService.CanStop() )
{
ExitCode = 1064; // ERROR_EXCEPTION_IN_SERVICE
throw new ApplicationException( $"Unable to stop service at this time." );
}
base.OnStop();
}
}
ServiceBase
,没有发现实现上有任何真正的差异。 有什么想法为什么我的版本无法工作吗?
本质上,我想防止在作业正在运行的情况下停止我的服务,但是,我确实有一个安全防护措施,如果在滑动窗口中请求停止足够多次,它将允许停止发生并终止运行工作。
您想要的是有更多的时间让您的服务开始。
ServiceBase.RequestAdditionalTime
请求额外时间。
WindowsServiceLifetime
确实源自 ServiceBase
,但没有现成的功能可以调用它。
SetServiceStatus
函数 (winsvc.h). 完成的
您需要找到适合您的特定情况的最佳方法。