我写了一项小型服务,该服务充当本地网络服务器。要编写服务,我遵循了有关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;
};
之后,我编写的服务代码简化为相关部分:
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);
}
}
主入口点很简单,因为:
static void Main(string[] args)
{
ServiceBase.Run(new Service());
}
您可以看到,错误消息的数量与SetServiceState
调用的数量匹配。如果我添加其他此类电话,则错误消息的数量会相应增加。
所以我假设,整个问题在我调用 SetServiceStatus
api的方式上,但我目前看不到问题。
您可以发现问题吗?
无论如何,这是使用C#和.NET构建服务的正确方法?
首先:
通常不必调用SetServiceState
方法。如果您的服务确实需要很长时间才能初始化(在这里您可以告诉SCM您仍然活着使用SERVICE_START_PENDING
,并且需要再几秒钟)。通常,您在OnStart
中启动线程并尽快返回。
我在C#中写了许多服务,从来没有需要这个。
但是 - 我在MSDN示例代码中找到了一个错误(我自己测试了您的代码)。
在ServiceStatus
结构中,用int或(更好的单位)替换长时间。如果使用UINT,则还必须在SetServiceState
方法中更改此。
还请参见dword映射到int或uint?。
如果您对小型介绍感兴趣,如何从C#中的Windows Service开始使用其他设置,则可以检查我的博客条目:
http://www.rsprog.de/samplewindowsservice/
[更新2018-01-20]
我创建了一篇有关它的新文章,该文章使用具有优势的自动安装方法(至少对我来说),它不需要Visual Studio的设置项目扩展
http://www.rsprog.de/windowsserviceselfinstall/