Topshelf 如何防止 Windows 服务停止

问题描述 投票:0回答:1

尝试在 .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();
    }
}

我查看了 .NET 7 版本的

ServiceBase
,没有发现实现上有任何真正的差异。 有什么想法为什么我的版本无法工作吗?

本质上,我想防止在作业正在运行的情况下停止我的服务,但是,我确实有一个安全防护措施,如果在滑动窗口中请求停止足够多次,它将允许停止发生并终止运行工作。

c# windows-services topshelf
1个回答
0
投票

您想要的是有更多的时间让您的服务开始。

为此,您需要致电

ServiceBase.RequestAdditionalTime
请求额外时间。

WindowsServiceLifetime
确实源自
ServiceBase
,但没有现成的功能可以调用它。

这是通过

SetServiceStatus
函数 (winsvc.h).

完成的

您需要找到适合您的特定情况的最佳方法。

© www.soinside.com 2019 - 2024. All rights reserved.