Windows 服务未在冷启动时启动
Windows Service not starting on cold boot
Windows 并不总是在冷启动时启动我的服务,大部分时间都是这样,但有时它无法启动,系统日志中出现 'Timeout was reached' 错误.
我在服务开始时添加了一行来转储时间以查看发生了什么。
经过大约 15 次关机和重启,我的服务终于没有启动。
查看应用程序事件日志,我在 8:18:29 看到 Windows 许可证验证事件,WMI 在 8:19:04 开始
但是当我查看我的日志文件时,我看到
'08:15:21: _tmain'
这意味着我的服务在这次重启时甚至没有加载,或者至少 'main' 没有被调用。
查看系统事件日志:
我在 8:18:57 看到事件 7009:等待 XXXX 服务连接时超时(30000 毫秒)。
在 'HKLM\System\CurrentControlSet\Control' 的注册表中,我将值 'ServicesPipeTimeout' 设置为 90000
我的服务可执行文件是 C++,支持基于 .Net 2.0 的 /clr
可执行文件也没有签名,我添加了
<generatePublisherEvidence enabled="false"/>
到 .config 文件,只是为了确定。
该服务依赖于事件日志,这显然是有效的。
这是 Windows 7 x64 VM,具有 4GB 内存和其他一些东西,但似乎在启动时会出现抖动,并且在获得网络连接时遇到问题。
如果我手动启动服务,它会在 5 秒内启动。
我不想将服务设置为“自动(延迟启动)”,因为这会在 Windows 启动后 2 分钟发生。
我不知道接下来要尝试什么,甚至不知道去哪里看。
任何指导将不胜感激。
谢谢。
[编辑]
这是我的代码的入口。请注意,在对服务执行任何操作之前,我正在写入日志,这些服务都在 MyService class.
中
int _tmain(int /*argc*/, TCHAR* /*argv*/[], TCHAR* /*envp*/[])
{
SaveStringToFile(L"C:\start.txt", CTime::GetCurrentTime().Format("%H:%M:%S") + L": _tmain\n");
SetUnhandledExceptionFilter( MyCustomFilter );
OutputDebugString(_T(__FUNCTION__));
CMyService Service;
启动期间可能存在竞争条件。如果事件日志在系统尝试启动您的服务之前尚未开始工作,并且存在对该日志的依赖性,这可能会导致您的服务失败。
也许你可以Change the order in which your service application is started with respect to the Log.
编辑 从评论中添加信息
根据我的经验,如果在初始化过程中执行过多操作,则确实存在无法启动服务可执行文件的危险。我只放入了必需品。在这种情况下,写入日志:(还包括 main 和 ServiceMain() 的片段以说明我之前提到的异常日志记录...)
////////////////////////////////////////////////////////
//
// InitService(void) - Service initialization
//
// Caution - limit what is done from this function.
// The service start function: SVC_ServiceStart()
// is limited in how much time can be allocated
// to start this executable before it times out.
//
////////////////////////////////////////////////////////
int InitService(void)
{
char buf[200];
sprintf(buf, "Monitoring started");
if(LOG_STRTSTOP==1)WriteToLog(buf);
return SVC_SUCCESS;
}
其中 我的 main() 和 ServiceMain() 看起来像这样:
void main()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "xyzMon";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
LogProgramFlow("Leaving main()");
}
void ServiceMain(int argc, char** argv)
{
int error, result;
pS = &s;
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 = 3000;
hStatus = RegisterServiceCtrlHandler( "xyzMon", (LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
if(LOG_ERR==1) WriteToLog("Registering Control Handler failed");
return;
}
// Initialize Service
error = InitService();
....
Windows 并不总是在冷启动时启动我的服务,大部分时间都是这样,但有时它无法启动,系统日志中出现 'Timeout was reached' 错误.
我在服务开始时添加了一行来转储时间以查看发生了什么。
经过大约 15 次关机和重启,我的服务终于没有启动。
查看应用程序事件日志,我在 8:18:29 看到 Windows 许可证验证事件,WMI 在 8:19:04 开始 但是当我查看我的日志文件时,我看到 '08:15:21: _tmain'
这意味着我的服务在这次重启时甚至没有加载,或者至少 'main' 没有被调用。
查看系统事件日志: 我在 8:18:57 看到事件 7009:等待 XXXX 服务连接时超时(30000 毫秒)。
在 'HKLM\System\CurrentControlSet\Control' 的注册表中,我将值 'ServicesPipeTimeout' 设置为 90000
我的服务可执行文件是 C++,支持基于 .Net 2.0 的 /clr 可执行文件也没有签名,我添加了
<generatePublisherEvidence enabled="false"/>
到 .config 文件,只是为了确定。
该服务依赖于事件日志,这显然是有效的。
这是 Windows 7 x64 VM,具有 4GB 内存和其他一些东西,但似乎在启动时会出现抖动,并且在获得网络连接时遇到问题。
如果我手动启动服务,它会在 5 秒内启动。
我不想将服务设置为“自动(延迟启动)”,因为这会在 Windows 启动后 2 分钟发生。
我不知道接下来要尝试什么,甚至不知道去哪里看。
任何指导将不胜感激。
谢谢。
[编辑] 这是我的代码的入口。请注意,在对服务执行任何操作之前,我正在写入日志,这些服务都在 MyService class.
中int _tmain(int /*argc*/, TCHAR* /*argv*/[], TCHAR* /*envp*/[])
{
SaveStringToFile(L"C:\start.txt", CTime::GetCurrentTime().Format("%H:%M:%S") + L": _tmain\n");
SetUnhandledExceptionFilter( MyCustomFilter );
OutputDebugString(_T(__FUNCTION__));
CMyService Service;
启动期间可能存在竞争条件。如果事件日志在系统尝试启动您的服务之前尚未开始工作,并且存在对该日志的依赖性,这可能会导致您的服务失败。
也许你可以Change the order in which your service application is started with respect to the Log.
编辑 从评论中添加信息
根据我的经验,如果在初始化过程中执行过多操作,则确实存在无法启动服务可执行文件的危险。我只放入了必需品。在这种情况下,写入日志:(还包括 main 和 ServiceMain() 的片段以说明我之前提到的异常日志记录...)
////////////////////////////////////////////////////////
//
// InitService(void) - Service initialization
//
// Caution - limit what is done from this function.
// The service start function: SVC_ServiceStart()
// is limited in how much time can be allocated
// to start this executable before it times out.
//
////////////////////////////////////////////////////////
int InitService(void)
{
char buf[200];
sprintf(buf, "Monitoring started");
if(LOG_STRTSTOP==1)WriteToLog(buf);
return SVC_SUCCESS;
}
其中 我的 main() 和 ServiceMain() 看起来像这样:
void main()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "xyzMon";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
LogProgramFlow("Leaving main()");
}
void ServiceMain(int argc, char** argv)
{
int error, result;
pS = &s;
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 = 3000;
hStatus = RegisterServiceCtrlHandler( "xyzMon", (LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
if(LOG_ERR==1) WriteToLog("Registering Control Handler failed");
return;
}
// Initialize Service
error = InitService();
....