如何调试 Windows 服务

发布于 2024-10-18 08:56:11 字数 1256 浏览 8 评论 0原文

我已经使用代码项目文章创建了一个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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

指尖上的星空 2024-10-25 08:56:11

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.

埋情葬爱 2024-10-25 08:56:11

您始终可以在调试模式下构建服务并将调试器附加到正在运行的服务。这种技术的唯一问题是您无法调试服务启动代码。出于这个原因,并且为了调试服务而不断注册/取消注册/启动/停止服务可能会很痛苦,我总是编写服务,以便它们也可以作为命令行程序运行。

如果 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 and GetLastError() returns ERROR_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.

请别遗忘我 2024-10-25 08:56:11

使用下面的代码来调试您的服务,将其放入服务启动函数中,它会给您一个弹出窗口并保持执行,直到您说“确定”或直到 60 秒,将断点放在下一个执行语句中,您可以继续调试 -

包括这个标题-

#include <Wtsapi32.h>
#pragma comment( lib, "Wtsapi32.lib" )

代码-

wchar_t title[] = L"service in startup - 60 seconds to take action";
wchar_t message[] = L"To debug, first attach to the process with Visual "
                    L"Studio, then click OK. If you don't want to debug, "
                    L"just click OK without attaching";
DWORD consoleSession = ::WTSGetActiveConsoleSessionId();
DWORD response;
BOOL ret = ::WTSSendMessage( WTS_CURRENT_SERVER_HANDLE,
                            consoleSession,
                            title, sizeof(title),
                            message, sizeof(message),
                            MB_OK,
                            60,
                            &response,
                            TRUE );

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-

#include <Wtsapi32.h>
#pragma comment( lib, "Wtsapi32.lib" )

Code-

wchar_t title[] = L"service in startup - 60 seconds to take action";
wchar_t message[] = L"To debug, first attach to the process with Visual "
                    L"Studio, then click OK. If you don't want to debug, "
                    L"just click OK without attaching";
DWORD consoleSession = ::WTSGetActiveConsoleSessionId();
DWORD response;
BOOL ret = ::WTSSendMessage( WTS_CURRENT_SERVER_HANDLE,
                            consoleSession,
                            title, sizeof(title),
                            message, sizeof(message),
                            MB_OK,
                            60,
                            &response,
                            TRUE );
半透明的墙 2024-10-25 08:56:11

我建议编写一个小记录器类,将信息写入文本文件。然后你可以输入类似的内容:

if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
    Logger.LogError("Service handler is 0.");
    return;
}    

while(running) {

   Logger.LogInfo("I am running.");

   //...
}

I would recommend to write a little Logger-Class, that writes information to a text-file. Then you can e.g. put something like:

if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
    Logger.LogError("Service handler is 0.");
    return;
}    

while(running) {

   Logger.LogInfo("I am running.");

   //...
}
九命猫 2024-10-25 08:56:11

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 a LocalService account so it has no connection to a physical desktop.

浮萍、无处依 2024-10-25 08:56:11

服务是无头的,因此尝试启动任何与 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).

抱猫软卧 2024-10-25 08:56:11

或者,可以将 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..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文