如何调试 Windows 服务
我已经使用代码项目文章创建了一个Windows服务。我可以使用 -i 和 -d 开关安装服务和删除服务。
我可以在 services.msc 中看到该服务,但是当我启动该服务时,它什么也不做。下面我将提供服务主要代码:
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
m_ServiceStatusHandle = RegisterServiceCtrlHandler("Service1",
ServiceCtrlHandler);
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
{
}
bRunning=true;
while(bRunning)
{
Sleep(150000);
ShellExecute(NULL, "open", "C:\\", NULL, NULL, SW_SHOWNORMAL);
}
return;
}
但是当我启动该服务时,它既不休眠也不启动资源管理器。我错过了什么吗?
I have create a windows service using the Code Project Article. I am able to install the service and delete the service using -i and -d switch.
I am able to see the service in services.msc but when I start the service it does nothing.Below I will proide the service main code:
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
m_ServiceStatusHandle = RegisterServiceCtrlHandler("Service1",
ServiceCtrlHandler);
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
{
}
bRunning=true;
while(bRunning)
{
Sleep(150000);
ShellExecute(NULL, "open", "C:\\", NULL, NULL, SW_SHOWNORMAL);
}
return;
}
But while I start the service neither it sleeps or starts the explorer. Am I missing anything?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
Ferruccio 关于将调试器附加到正在运行的服务的建议是一个很好的建议,就像包含一个作为控制台应用程序运行的选项的建议一样(尽管这对您的情况没有帮助)。
要调试启动代码,可以调用 DebugBreak() 位于启动代码的开头。这将启动调试器并在此时暂停服务的执行。进入调试器后,设置所需的断点,然后继续执行。
Ferruccio's suggestion to attach a debugger to the running service is a good one, as is the suggestion to include an option to run as a console application (though that won't help in your case).
To debug the startup code, you can call DebugBreak() at the beginning of your startup code. That will launch the debugger and pause execution of your service at that point. Once you are in the debugger, set whatever breakpoints you need and then continue execution.
您始终可以在调试模式下构建服务并将调试器附加到正在运行的服务。这种技术的唯一问题是您无法调试服务启动代码。出于这个原因,并且为了调试服务而不断注册/取消注册/启动/停止服务可能会很痛苦,我总是编写服务,以便它们也可以作为命令行程序运行。
如果
StartServiceCtrlDispatcher()
失败并且GetLastError()
返回ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
,您的服务可以判断它是从命令行启动的。当然,当您从命令行运行服务时,它可以访问桌面,而服务通常无法访问桌面,并且它在当前登录用户的上下文中运行,而不是在本地系统或指定帐户的上下文中运行,因此您需要以这种方式调试服务时请考虑这些差异。
You can always build a service in debug mode and attach a debugger to the running service. The only problem with this technique is that you can't debug the service start-up code. For this reason and for the fact that it can be a pain to be constantly registering/unregistering/starting/stopping a service in order to debug it, I always write services so that they can also be run as command line programs.
Your service can tell that it was started from the command line if
StartServiceCtrlDispatcher()
fails andGetLastError()
returnsERROR_FAILED_SERVICE_CONTROLLER_CONNECT
.Of course, when you run a service from the command line it has access to the desktop, which a service normally doesn't and it's running in the context of the currently logged in user, rather than LocalSystem or a specified account so you need to take these differences into account when debugging a service in this manner.
使用下面的代码来调试您的服务,将其放入服务启动函数中,它会给您一个弹出窗口并保持执行,直到您说“确定”或直到 60 秒,将断点放在下一个执行语句中,您可以继续调试 -
包括这个标题-
代码-
Use below code to debug your service, put this in service startup function, it will give you a popup and hold the execution until you say OK or until 60 seconds, put the breakpoint in the next execution statement and you can proceed with debugging -
Include this header-
Code-
我建议编写一个小记录器类,将信息写入文本文件。然后你可以输入类似的内容:
I would recommend to write a little Logger-Class, that writes information to a text-file. Then you can e.g. put something like:
此处,尽管乍一看我认为您正在使用需要桌面交互的
ShellExecute
。服务通常在LocalService
帐户上运行,因此它没有与物理桌面的连接。I've got some general tips on debugging windows services here, though at first glance I think it's the fact that you're using
ShellExecute
which requires desktop interaction. A service typically runs on aLocalService
account so it has no connection to a physical desktop.服务是无头的,因此尝试启动任何与 GUI 相关的内容将不会产生可见的效果。 ShellExecute 将在服务的可视上下文中启动应用程序,您的桌面将无法看到该应用程序。
如果您想证明您的服务正在执行某些操作,请向文件系统写入一些内容(或者相信它正在运行,因为服务管理器有足够的能力告诉您它是否没有运行)。
Services are headless, so trying to fire up anything GUI related will result in no visible effect. ShellExecute would fire up an application in the visual context of the service, which your desktop will not be able to see.
If you want to prove that your service is doing something, write something to file system instead (or trust that it's running given the service manager is rather well equipped to tell you if it's not).
或者,可以将 OutputDebugString() 放入服务应用程序中,并可以在 DbgView 中看到打印内容。我这样做是为了调试我的服务应用程序。
希望这对某人有帮助..
Alternatively, OutputDebugString() can be put in the service app and prints can be seen in DbgView. I have done it to debug my service application.
Hope this helps somebody..