第一次写Windows下的服务程序,无法启动

时间:2022-09-22 17:09:11
我想做一个服务来监测某个程序的运行情况,于是在网上找了一些资料,试着写了一下,发现无法启动起来。
开发环境为VS2005
首先建一个空的Console Application,写了Main(),ServiceMain()和ControlHandler(),Build一个exe,然后用了命令行安装服务的方法:sc create MemoryStatus binpath= c:\MyServices\MemoryStatus.exe,创建成功,然后用服务控制面板来启动这个服务,总是出错:1053,服务并未及时相应请求。

另外,弱弱地问一下,这样写成的能用F5来调试吗?

还有,我发现有的资源上要求建一个Win32 Appllcation,自己要写install和uninstall,哪样写更好呢

15 个解决方案

#1


代码如下:
void main()
{
SERVICE_TABLE_ENTRYA ServiceTable[2];
ServiceTable[0].lpServiceName = SERVERNAME;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;

if (StartServiceCtrlDispatcher((SERVICE_TABLE_ENTRYW *)ServiceTable))
{
printf("StartServiceCtrlDispatcher failed");
return;
}
}
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
hStatus = RegisterServiceCtrlHandler((LPTSTR)SERVERNAME, (LPHANDLER_FUNCTION)ControlHandler);

if (hStatus == 0)
{
printf("RegisterServiceCtrlHandler failed");
return;
}

ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 10000;

if (SetServiceStatus(hStatus, &ServiceStatus))
{
    return;
}

if (InitService() == -1)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);
CloseHandle(hStatus);
return;
}

ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);

}
int InitService()
{
int nResult;
nResult = WriteToLog("Monitoring start");
return nResult;
}

void WINAPI ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
ServiceStatus.dwWaitHint = 3000;
ServiceStatus.dwCheckPoint = 1;
SetServiceStatus(hStatus, &ServiceStatus);

ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);

CloseHandle(hStatus);
return;
default:
break;
}
}

#2


study...
up

#3


给你两个链接
http://www.vckbase.com/document/viewdoc/?id=1474
http://www.vckbase.com/document/viewdoc/?id=1447
看懂了就会了,呵呵

#4


我的代码就是按照上面的第一个链接写的,可是启动不了

#5


up

#6


你的ServiceMain函数有问题,SetServiceStatus函数的dwCurrentState不是SERVICE_RUNNING,改成这样:
-------------------------------------------------------------------
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
hStatus = RegisterServiceCtrlHandler((LPTSTR)SERVERNAME, (LPHANDLER_FUNCTION)ControlHandler);

if (hStatus == 0)
{
printf("RegisterServiceCtrlHandler failed");
return;
}

ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 10000;
if (SetServiceStatus(hStatus, &ServiceStatus))
{
    return;
}

if (InitService() == -1)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);
CloseHandle(hStatus);
return;
}
}
-------------------------------------------------------------------

#7


faint,没注意你原来SetServiceStatus那句还有问题,那句改一下:
if (SetServiceStatus(hStatus, &ServiceStatus))
改为:
if (!SetServiceStatus(hStatus, &ServiceStatus))

#8


就是说,你原来的程序中,第一个SetServiceStatus函数通知SCM服务程序状态为SERVICE_START_PENDING成功之后,由于你那个判断语句错误,直接就return走了,所以后面的程序执行不到,无法通知SCM服务已经启动,导致出错。
所以按照我上一个帖子修改掉那个判断语句就ok了;或者也可以按照我回复你的第一个帖子那样,不将服务置为SERVICE_START_PENDING状态,直接将服务置为SERVICE_RUNNING状态。不过同样需要修改那个判断语句,否则后面的就执行不到了

#9


http://topic.csdn.net/u/20070923/15/05698dda-5eb3-4b01-b685-4ef5a9d1decc.html

#10


up

#11


谢谢各位的解答。
关于那个SetServiceStatus的判断语句的问题我昨天就已经发现并改过了,不过仍然是启动不了,错误为:在本地计算机无法启动×××服务,错误1053:服务没及时响应启动或控制请求

#12


to nkgd(长歌天下)

如你所说,将dwCurrentState设为SERVICE_RUNNING后,确实能启动,可是为什么,照我写的,我先设为SERVICE_START_PENDING,再设为SERVICE_RUNNING,这样不行吗?
还有啊,这样的错误该怎么调试

#13


如果你修改了那个判断语句,修改为:
if   (!SetServiceStatus(hStatus,   &ServiceStatus)) 

        return; 


的话,那么应该是可以启动的,还是启动不了的话,检查一下你的那个InitService函数,如果它返回-1,那同样无法到达通知SCM服务已经SERVICE_RUNNING的地方,把InitService修改为这样测试一下:
int   InitService() 

return 0;
}

这样就不应该失败了

#14


至于调试服务,是比较麻烦一点的,看这里吧:
http://msdn2.microsoft.com/zh-cn/library/7a50syb3(VS.80).aspx

#15


mark

#1


代码如下:
void main()
{
SERVICE_TABLE_ENTRYA ServiceTable[2];
ServiceTable[0].lpServiceName = SERVERNAME;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;

if (StartServiceCtrlDispatcher((SERVICE_TABLE_ENTRYW *)ServiceTable))
{
printf("StartServiceCtrlDispatcher failed");
return;
}
}
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
hStatus = RegisterServiceCtrlHandler((LPTSTR)SERVERNAME, (LPHANDLER_FUNCTION)ControlHandler);

if (hStatus == 0)
{
printf("RegisterServiceCtrlHandler failed");
return;
}

ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 10000;

if (SetServiceStatus(hStatus, &ServiceStatus))
{
    return;
}

if (InitService() == -1)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);
CloseHandle(hStatus);
return;
}

ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);

}
int InitService()
{
int nResult;
nResult = WriteToLog("Monitoring start");
return nResult;
}

void WINAPI ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
ServiceStatus.dwWaitHint = 3000;
ServiceStatus.dwCheckPoint = 1;
SetServiceStatus(hStatus, &ServiceStatus);

ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);

CloseHandle(hStatus);
return;
default:
break;
}
}

#2


study...
up

#3


给你两个链接
http://www.vckbase.com/document/viewdoc/?id=1474
http://www.vckbase.com/document/viewdoc/?id=1447
看懂了就会了,呵呵

#4


我的代码就是按照上面的第一个链接写的,可是启动不了

#5


up

#6


你的ServiceMain函数有问题,SetServiceStatus函数的dwCurrentState不是SERVICE_RUNNING,改成这样:
-------------------------------------------------------------------
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
hStatus = RegisterServiceCtrlHandler((LPTSTR)SERVERNAME, (LPHANDLER_FUNCTION)ControlHandler);

if (hStatus == 0)
{
printf("RegisterServiceCtrlHandler failed");
return;
}

ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 10000;
if (SetServiceStatus(hStatus, &ServiceStatus))
{
    return;
}

if (InitService() == -1)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);
CloseHandle(hStatus);
return;
}
}
-------------------------------------------------------------------

#7


faint,没注意你原来SetServiceStatus那句还有问题,那句改一下:
if (SetServiceStatus(hStatus, &ServiceStatus))
改为:
if (!SetServiceStatus(hStatus, &ServiceStatus))

#8


就是说,你原来的程序中,第一个SetServiceStatus函数通知SCM服务程序状态为SERVICE_START_PENDING成功之后,由于你那个判断语句错误,直接就return走了,所以后面的程序执行不到,无法通知SCM服务已经启动,导致出错。
所以按照我上一个帖子修改掉那个判断语句就ok了;或者也可以按照我回复你的第一个帖子那样,不将服务置为SERVICE_START_PENDING状态,直接将服务置为SERVICE_RUNNING状态。不过同样需要修改那个判断语句,否则后面的就执行不到了

#9


http://topic.csdn.net/u/20070923/15/05698dda-5eb3-4b01-b685-4ef5a9d1decc.html

#10


up

#11


谢谢各位的解答。
关于那个SetServiceStatus的判断语句的问题我昨天就已经发现并改过了,不过仍然是启动不了,错误为:在本地计算机无法启动×××服务,错误1053:服务没及时响应启动或控制请求

#12


to nkgd(长歌天下)

如你所说,将dwCurrentState设为SERVICE_RUNNING后,确实能启动,可是为什么,照我写的,我先设为SERVICE_START_PENDING,再设为SERVICE_RUNNING,这样不行吗?
还有啊,这样的错误该怎么调试

#13


如果你修改了那个判断语句,修改为:
if   (!SetServiceStatus(hStatus,   &ServiceStatus)) 

        return; 


的话,那么应该是可以启动的,还是启动不了的话,检查一下你的那个InitService函数,如果它返回-1,那同样无法到达通知SCM服务已经SERVICE_RUNNING的地方,把InitService修改为这样测试一下:
int   InitService() 

return 0;
}

这样就不应该失败了

#14


至于调试服务,是比较麻烦一点的,看这里吧:
http://msdn2.microsoft.com/zh-cn/library/7a50syb3(VS.80).aspx

#15


mark