【问题标题】:Windows service can't be stoppedWindows 服务无法停止
【发布时间】:2018-06-28 14:37:43
【问题描述】:

我的 Windows 服务有问题。有时服务无法停止并以运行状态挂起)在带有消息的启动命令之后: The service cannot accept control messages at this time

简化的服务实现:

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

【问题讨论】:

  • 有时在开发服务时会发生这种情况,而您在构建时尝试再次部署。尝试重新启动计算机以查看是否可以解决问题。 (出于这个原因,在 VM 中开发服务通常是一个好主意)
  • //Some stop logic里面的代码是什么,你确定没有卡在那里?
  • 尝试使用命令行。 “网络停止 [ServiceName]”。还有“SC STOP [SERVICENAME]”和“SC DELETE [SERVICENAME]”
  • 这在开发人员的环境中不会发生。用户尝试通过 MSI 更新软件,但安装程序无法停止服务,当您尝试手动停止服务时,您会看到这样的消息。
  • 我知道如何停止服务问题是为什么会发生。而且我 100% 确定 stop 方法永远不会被命中,因为我在方法的开头有一个内部变量,并且在锁定之前有一些日志记录行。我检查了windbg中的变量,OnStop方法从未被命中。

标签: c# .net windows-services


【解决方案1】:

在您的示例中,PerformHealthCheck() 将不确定地运行。因此,您的 OnStart 永远不会完成。不知道这是否只是因为您的简化示例。

但是,当它发生时,你真的会记录一些东西吗?如,记录 OnStart 方法的结束,并确认问题发生时, OnStart 实际上已完成。在您的代码评论中,您写了//Code is not reachabl.. 您是否也在那里记录了一些东西?还是在锁内?

顺便说一句,锁定启动和停止似乎是同步的好主意,但作为用户,如果我想停止服务,我真的想停止它。不管它仍然处于启动状态。事实上,如果服务没有响应停止命令,我怀疑 90% 的时间,任务管理器无论如何都是下一个停止...如果您尝试以这样的方式重写停止逻辑不是更好吗?它总是会执行并中断它所能做的一切吗?这可能会解决您的问题并改善 imo 体验。

编辑,似乎锁实际上并没有做任何事情(至少,如果它们只在这里使用而不是在其他地方锁定某些东西)如果 OnStop 命令仍然是 StartPending,操作系统将不会通过它。 :

当启动只需要很长时间并且在启动完成之前调用一次停止时,是否可能会发生这种情况?看这个例子:

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; OnStart 退出

注意不要停

即使在 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 方法已完成。
  • 感谢您的回答!确实是这样,在 OnStart 方法完成之前服务就停止了,导致状态损坏(不能接受任何新消息,没有调用 OnStop 方法)
【解决方案2】:

我的问题是,当我想删除旧版本时,无法停止正在运行的 Pulse Secure Service。我是这样解决的:

转到 Windows 开始 -> 管理工具 -> 服务

找到 Pulse Secure。

右键->属性->启动类型->选择禁用

重启 Windows

卸载旧版 Pulse Secure:

开始 -> Windows 系统 -> 控制面板 -> 程序 -> 卸载程序 -> 在那里卸载

之后,新安装就没有问题了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多