3

我已经使用代码项目文章创建了一个 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;
}

但是,当我启动服务时,它既不会休眠也不会启动资源管理器。我错过了什么吗?

4

7 回答 7

5

Ferruccio 建议将调试器附加到正在运行的服务是一个很好的建议,建议包括一个作为控制台应用程序运行的选项(尽管这对您的情况没有帮助)。

要调试启动代码,您可以在启动代码的开头调用DebugBreak() 。这将启动调试器并暂停执行您的服务。进入调试器后,设置所需的任何断点,然后继续执行。

于 2012-04-13T12:07:02.787 回答
3

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.

于 2011-02-21T14:16:28.380 回答
1

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

包括这个标题 -

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

代码-

wchar_t title[] = L"mrnservice 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 );
于 2019-06-28T13:26:59.703 回答
0

服务是无头的,因此尝试启动任何与 GUI 相关的东西都不会产生明显的效果。ShellExecute 将在服务的可视上下文中启动应用程序,您的桌面将无法看到该应用程序。

如果您想证明您的服务正在做某事,请改为将某些内容写入文件系统(或者相信它正在运行,因为服务管理器可以很好地告诉您是否没有)。

于 2011-02-21T12:02:27.557 回答
0

我建议编写一个小 Logger-Class,将信息写入文本文件。然后你可以例如放一些东西:

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

while(running) {

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

   //...
}
于 2011-02-21T12:15:11.690 回答
0

我在这里有一些关于调试 Windows 服务的一般提示,但乍一看,我认为这是您使用的事实,ShellExecute它需要桌面交互。服务通常在LocalService帐户上运行,因此它与物理桌面没有连接。

于 2011-02-21T13:30:58.860 回答
-1

或者,可以将 OutputDebugString() 放入服务应用程序中,并且可以在 DbgView 中查看打印。我已经完成它来调试我的服务应用程序。希望这可以帮助某人..

于 2013-10-24T05:37:51.993 回答