1

每个人

我想知道如何在 C 中调试 windows 服务启动代码。有几个这样的问题,但在 C# 中,但它们不是我需要的。到目前为止,我只能附加到进程来调试。现在我想调试main()函数,怎么办?越详细越好。

非常感谢。

我的代码如下。

主功能:

void main()
{   
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = "MemoryStatus";  
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; //ServiceMain
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;

    StartServiceCtrlDispatcher(ServiceTable);
}

服务主要功能:

void ServiceMain(int argc, char** argv)
{        
    //...some codes....

    hStatus = RegisterServiceCtrlHandler("MemoryStatus",(LPHANDLER_FUNCTION)ControlHandler);

    //...some codes....

    //the worker loop of a service
    while(ServiceStatus.dwCurrentState == SERVICE_RUNNING)
    {
        char buffer[10];        
        sprintf(buffer,"login...");
        int result = WriteToLog(buffer);        
        if (result)
        {
             ReportStatus(SERVICE_STOPPED,-1);
             return;
        }
        Sleep(SLEEP_TIME);
    }
    return;
}

控制手柄功能:

void ControlHandler(DWORD request)
{
    switch(request)
    {
    case SERVICE_CONTROL_STOP:
        WriteToLog("Monitoring stopped.");
        //...Report Status to SCM code....
        return;
    case SERVICE_CONTROL_SHUTDOWN:
        WriteToLog("Monitoring stopped.");
        //...Report Status to SCM code....
        return;
    default:
        break;
    }
//...Report Status to SCM code....
    return;
}
4

2 回答 2

2

有两种不同的方法可以从一开始就调试 Windows 服务。两者都在这里描述。

我的首选包括使用以服务开头的远程调试器会话(您可以ntsd从 Windows 调试工具中使用)。Windows 中有一种特殊的机制,可以让您根据图像名称(图像文件执行选项)劫持进程。您可以在下面找到 .reg 文件的内容,该文件将为您设置此调试器(将路径更改为您安装了调试工具的路径):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\svchost.exe]
"Debugger"="\"C:\\tools\\debugging\\Debugging Tools for Windows (x64)\\ntsd.exe\" -server npipe:pipe=svcpipe -noio"

下一步是使用用户模式调试器附加到此会话:

windbg -remote "npipe:pipe=svcpipe,server=localhost"

你已经准备好调试了。请记住在重新启动计算机之前删除注册表设置,否则 Windows 将挂起并显示黑屏 :)

于 2012-10-15T19:23:50.237 回答
0

OK,有两种方法:首先,我们可以在代码开始时休眠服务进程。像这样:

main()
{
    sleep(10);
    .....
}

然后附加到服务进程,调试器将停止在断点位置,因为我们有 10 秒的等待时间。

其次,我们可以在代码的开头使用_ASSERT(FALSE)或函数。DebugBreak()

于 2013-12-12T02:04:00.670 回答