Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何调试Windows服务_C++_Windows_Windows Services_Window_Servicecontroller - Fatal编程技术网

C++ 如何调试Windows服务

C++ 如何调试Windows服务,c++,windows,windows-services,window,servicecontroller,C++,Windows,Windows Services,Window,Servicecontroller,我已经使用本文创建了一个windows服务。我可以使用-I和-d开关安装服务和删除服务 我可以在services.msc中看到该服务,但当我启动该服务时,它什么也不做。下面我将提供服务主代码: void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { DWORD status; DWORD specificError; m_ServiceStatus.dwServiceType = SERVICE_WIN32; m_ServiceSt

我已经使用本文创建了一个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;
}

但当我启动服务时,它既不睡眠也不启动浏览器。我遗漏了什么吗?

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


如果您想证明您的服务正在做一些事情,请改为向文件系统写入一些内容(或者相信它正在运行,因为服务管理器已经准备好告诉您它是否正在运行)。

我建议编写一个小日志类,将信息写入文本文件。然后你可以放一些东西,比如:

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

while(running) {

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

   //...
}

我有一些调试windows服务的一般技巧,不过乍一看,我认为这是因为您使用的是需要桌面交互的
ShellExecute
。服务通常在
LocalService
帐户上运行,因此它与物理桌面没有连接

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

如果
StartServiceCtrlDispatcher()
失败,并且
GetLastError()
返回
ERROR\u FAILED\u service\u CONTROLLER\u CONNECT
,您的服务可以从命令行判断它是启动的


当然,当您从命令行运行服务时,它可以访问桌面,而服务通常不会访问桌面,并且它正在当前登录用户的上下文中运行,而不是LocalSystem或指定的帐户,因此在以这种方式调试服务时需要考虑这些差异。

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


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

或者,可以将OutputDebugString()放入服务应用程序中,并在DbgView中查看打印。我这样做是为了调试我的服务应用程序。
希望这对某人有所帮助。

使用下面的代码调试您的服务,将其放入服务启动功能中,它将弹出一个窗口并保持执行直到您说OK或60秒,将断点放入下一个执行语句中,您可以继续调试-

包括此标题-

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

资源管理器始终在Windows上运行,因此不会重新启动它。查看您的任务管理器,了解正在发生的事情。您希望从这段代码中得到什么?“当我启动服务时,它什么也不做”是什么意思?如果您需要某个窗口,则应更改服务属性并设置“允许服务与桌面交互”复选框。看起来您正在尝试每隔150秒打开一个新的资源管理器窗口(假设该服务标记为“允许桌面交互”)。如果这是您的服务所做的全部工作,您最好设置一个计划程序任务来完成此工作。@Dims使服务在开始执行您的代码之前崩溃(您将DebugBreak()放在那里),或者您错误地认为代码的哪一部分是先执行的。首先,确认DebugBreak()作为非常简单的控制台可执行文件的第一行对您有效。(您可能没有配置JIT调试。)一旦工作正常,请重试该服务。如果您确定要执行的第一段代码是DebugBreak()它仍然没有进入调试器,这意味着它正在服务框架中崩溃。获取一个新框架。
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 );