Windows 服务无法停止。

3

我有一个与Windows服务相关的问题。有时在启动命令后,服务无法停止并处于运行状态,并显示以下消息:

该服务目前无法接受控制信息

简化的服务实现如下:

using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class Service : ServiceBase
    {
        protected object SyncRoot { get; } = new object();
        protected override void OnStart(string[] args)
        {
            lock (SyncRoot)
            {
                var task = PerformHealthCheck();

                while (!task.Wait(10000))
                {
                    RequestAdditionalTime(10000);
                }

                Task.Factory.StartNew(() =>
                {
                    //Some logic to start worker threads and initialize some startup processes
                    //All workers threads actually successfully executed.
                }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
            }
        }

        protected override void OnStop()
        {
            //Code is not reachable sometimes
            lock (SyncRoot)
            {
                //Some stop logic
            }
        }

        private static async Task PerformHealthCheck()
        {
            int status = 0;
            do
            {
                status = CheckStatus();
                if (status == 0)
                {
                    await Task.Delay(20000);
                }
            }
            while (status == 0);
        }

        private static int CheckStatus()
        {
            //Calculating HealthCheck status
            return 0;
        }
    }
}

创建逻辑:

internal static class Program
{
    private static void Main(string[] args)
    {
        ServiceBase.Run(new Service());
    }
}

OnStart 方法已成功执行到结束,而 OnStop 方法甚至未被触发。我可以在 WinDbg 中看到以下服务状态:

16 serviceType
4 currentState
5 controlsAccepted
0 win32ExitCode
0 serviceSpecificExitCode
0 checkPoint
0 waitHint

据我所知,该服务处于运行状态并已接收停止命令,但未执行(从日志中可以看出)。我不明白有什么可能会阻止服务执行OnStop方法。在Windows事件视图中可以看到启动命令,但没有停止命令。

其他信息:

  • .NET 4.5框架
  • Windows Server 2012-2016

有时在开发服务时,在构建过程中尝试重新部署时会出现这种情况。尝试重新启动计算机,看看是否可以解决问题。(基于这个原因,在虚拟机中开发服务通常是一个好主意) - user585968
//Some stop logic 内的代码是什么?你确定它没有卡在那里吗? - DavidG
尝试使用命令行。 "net stop [ServiceName]"。还有"SC STOP [SERVICENAME]"和"SC DELETE [SERVICENAME]" - Wheels73
这在开发环境中并没有发生。用户尝试通过MSI更新软件,但安装程序无法停止服务,当您尝试手动停止服务时,会看到这样的消息。 - Andrew
我知道如何停止服务,问题是为什么会发生这种情况。我可以百分之百确定停止方法从未被触发,因为我在方法开始处有一个内部变量和一些日志记录行,就在锁定之前。我在windbg中检查了变量,OnStop方法从未被触发。 - Andrew
听起来你的启动逻辑卡住了,持有OnStop想要进入的锁。 - 500 - Internal Server Error
2个回答

4
在你的例子中,PerformHealthCheck()将无限运行。因此,你的OnStart永远不会结束。不知道这是否仅是因为你简化了例子。
然而,当它发生时,你实际上是否记录了一些东西?比如,在记录OnStart方法结束时,并确认在出现问题时,OnStart确实已经完成。在你的代码注释中,你写道//Code is not reachabl..,你在那里也记录了一些东西吗?或者在锁内部?
顺便说一句,锁定启动和停止可能看起来像一个很好的同步方法,但作为用户,如果我想停止一个服务,我真的想停止它。无论它是否仍处于启动状态。事实上,如果一个服务没有响应停止命令,我怀疑90%的时间,任务管理器是下一个停止的地方...难道不是更好,如果你尝试以这样的方式重写停止逻辑,它将总是执行并中断它能够中断的所有东西?这可能解决你的问题,并且在我看来也可以改善体验。
编辑,事实上锁定似乎根本没有任何作用(至少,如果它们只在这里使用,而不是在其他地方锁定)如果仍处于StartPending状态,操作系统不会传递OnStop命令..:
这可能发生在启动需要很长时间并且在启动完成之前调用了停止的情况下吗?请参见此示例:
class logger
{
    static readonly object _logSync = new object();

    public void Log(string message)
    {
        var m = $"{DateTime.Now.ToString("HH:mm:ss")}; {message}{Environment.NewLine}";
        lock(_logSync)
        {
            File.AppendAllText(@"C:\temp\test.txt", m);
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        ServiceBase.Run(new TestHangService());
    }
}
class TestHangService : ServiceBase
{
    private logger _log;

    public TestHangService()
    {
        _log = new logger();
    }

    protected override void OnStart(string[] args)
    {
        _log.Log("OnStart");
        Thread.Sleep(30 * 1000);
        _log.Log("OnStart exit");
    }

    protected override void OnStop()
    {
        _log.Log("OnStop");
    }
}

那么

C:\WINDOWS\system32>sc create DeleteMe binpath="C:\testprojects\TestService\TestService\bin\Debug\TestService.exe"
[SC] CreateService SUCCESS

C:\WINDOWS\system32>sc start deleteMe

SERVICE_NAME: deleteMe
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 2  START_PENDING
                            (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x7d0
    PID                : 27376
    FLAGS              :

C:\WINDOWS\system32>echo "executed directly after starting"
"executed directly after starting"

C:\WINDOWS\system32>sc stop deleteMe

SERVICE_NAME: deleteMe
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 2  START_PENDING
                            (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0

C:\WINDOWS\system32>echo "waiting for 30 sec"
"waiting for 30 sec"

C:\WINDOWS\system32>sc stop deleteMe
[SC] ControlService FAILED 1061:

The service cannot accept control messages at this time.

需要记录的内容是:

18:32:20; 开始

18:32:50; 开始退出

注意不是onstop

似乎无法恢复(这让我惊讶),即使过了10分钟也是如此:

C:\WINDOWS\system32>sc query deleteme

SERVICE_NAME: deleteme
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 4  RUNNING
                            (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0

C:\WINDOWS\system32>sc stop deleteme
[SC] ControlService FAILED 1061:

The service cannot accept control messages at this time.

这只是一个简化的例子。OnStart已经完成,我可以在日志和Windows事件视图中看到它。我还记录了很多东西,包括在锁定之前的OnStop方法的开始,当然没有被触发。我必须使用公司框架来创建服务,这就是为什么存在锁的原因。但是我的问题是,由于某种原因,OnStop方法从未被调用,但OnStart方法已经完成。 - Andrew
谢谢你的回答!确实是这种情况,服务在OnStart方法完成之前停止,导致状态损坏(无法接受任何新消息,OnStop方法也不会被调用)。 - Andrew

0
我的问题是当我想要删除旧版本时,运行的Pulse Secure服务无法停止。我解决了这个问题:
1. 前往Windows开始菜单 -> 管理工具 -> 服务
2. 找到Pulse Secure。
3. 右键单击 -> 属性 -> 启动类型 -> 选择禁用
4. 重启Windows
5. 卸载旧版本的Pulse Secure:
开始 -> Windows系统 -> 控制面板 -> 程序 -> 卸载程序 -> 在那里卸载它
6. 完成以上步骤后,新安装就可以顺利进行了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接