服务导致SCM错误"报告无效的当前状态0"

Flo*_*dis 6 .net c# service

我写了一个小服务,它充当本地网络服务器.为了编写服务,我按照MSDN教程,如何使用ServiceBase该类编写服务.

但是当我注册并启动服务时,我收到错误消息,如下所示.我在开始和服务停止时得到这些错误消息中的两个.(示例=服务名称).

示例服务报告了无效的当前状态0.

这是我服务的最小样本,包含所有相关部分.代码以MSDN教程中提供的枚举和结构定义开头:

public enum ServiceState
{
    SERVICE_STOPPED = 0x00000001,
    SERVICE_START_PENDING = 0x00000002,
    SERVICE_STOP_PENDING = 0x00000003,
    SERVICE_RUNNING = 0x00000004,
    SERVICE_CONTINUE_PENDING = 0x00000005,
    SERVICE_PAUSE_PENDING = 0x00000006,
    SERVICE_PAUSED = 0x00000007,
}

[StructLayout(LayoutKind.Sequential)]
public struct ServiceStatus
{
    public long dwServiceType;
    public ServiceState dwCurrentState;
    public long dwControlsAccepted;
    public long dwWin32ExitCode;
    public long dwServiceSpecificExitCode;
    public long dwCheckPoint;
    public long dwWaitHint;
};
Run Code Online (Sandbox Code Playgroud)

在此之后,我写的服务代码减少到相关部分:

namespace example
{
    public partial class Service : ServiceBase
    {
        public Service()
            : base()
        {
            this.ServiceName = "ExampleService";
            this.AutoLog = false;
            this.CanStop = true;
            this.CanShutdown = false;
            this.CanPauseAndContinue = false;
            this.CanHandlePowerEvent = false;
            this.CanHandleSessionChangeEvent = false;
        }

        protected override void OnStart(string[] args)
        {
            try {
                SetServiceState(ServiceState.SERVICE_START_PENDING, 100000);
                // ... initialise and start...
                SetServiceState(ServiceState.SERVICE_RUNNING);
            } catch (System.Exception ex) {
                SetServiceState(ServiceState.SERVICE_STOPPED);
            }
        }

        protected override void OnStop()
        {
            SetServiceState(ServiceState.SERVICE_STOP_PENDING, 100000);
            // ... stop service ... 
            SetServiceState(ServiceState.SERVICE_STOPPED);
        }

        private void SetServiceState(ServiceState state, int waitHint = 0)
        {
            ServiceStatus serviceStatus = new ServiceStatus();
            serviceStatus.dwCurrentState = state;
            serviceStatus.dwWaitHint = waitHint;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);
        }

        [DllImport("advapi32.dll", SetLastError=true)]
        private static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus);
    }
}
Run Code Online (Sandbox Code Playgroud)

主要切入点很简单,因为:

static void Main(string[] args)
{
    ServiceBase.Run(new Service());
}
Run Code Online (Sandbox Code Playgroud)

如您所见,错误消息的数量与SetServiceState调用的数量相匹配.如果我添加其他此类调用,则错误消息的数量会相应增加.

所以我假设,整个问题都在我调用SetServiceStatusAPI 的方式,但我目前看不到问题.

你能发现问题吗?

无论如何,这是使用C#和.NET构建服务的正确方法吗?

Rai*_*ack 14

第一:

通常没有必要调用该SetServiceState方法.如果您的服务确实需要很长时间来初始化(可以告诉SCM您还活着SERVICE_START_PENDING并需要几秒钟),则可能需要它.通常,您启动一​​个线程OnStart并尽快返回.

我在过去的几年里用C#编写了许多服务,但从来没有这样做过.

但是 - 我在MSDN示例代码中发现了一个错误(我自己测试了您的代码).

ServiceStatusstruct中用int替换long或(更好的单位).如果您使用uint,则还必须在SetServiceState方法中更改此设置.

另见DWORD映射到int还是uint?.

如果您对如何在C#中使用其他设置启动Windows服务感兴趣,可以查看我的博客条目:

http://www.rsprog.de/samplewindowsservice/

[更新2018-01-20]

我创建了一篇关于它的新文章,该文章使用了自我安装方法,该方法具有优势(至少对我而言),它不需要Visual Studio的安装项目扩展

http://www.rsprog.de/windowsserviceselfinstall/