为什么 运行 Windows 服务的进程 ID 为零 (QueryServiceStatusEx)?

Why is process ID of running Windows services zero (QueryServiceStatusEx)?

我需要确定 Windows 服务的进程 ID(我使用的是 C)。看到我可以访问服务的SC_HANDLE,QueryServiceStatusEx正是我需要的功能。但是,当访问QueryServiceStatusEx返回的SERVICE_STATUS_PROCESS结构中的dwProcessId字段时,它包含0。 这是我的代码:

unsigned int get_svc_pid (SC_HANDLE svc) {

    unsigned int pid = 0;
    BYTE *svc_info = NULL;
    DWORD buf_size = 0;
    DWORD bytes_needed = 0;
    //determine svc_info size
    QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO, svc_info, buf_size, &bytes_needed);
    svc_info = malloc(bytes_needed);
    buf_size = bytes_needed;
    //get pid
    if(QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO, svc_info, buf_size, &bytes_needed) != 0){
        pid = (*(SERVICE_STATUS_PROCESS *)svc_info).dwProcessId;
    }else{
        fprintf(msglog, "ERR: QueryServiceStatusEx failed\nGLE: %u\n", (unsigned int) GetLastError());
    }
    free(svc_info);
    return pid;
}

此外:我已经使用 EnumServiceStatusEx 枚举所有 运行 服务并输出它们的名称和包含在 ENUM_SERVICE_STATUS_PROCESS 结构中的 PID。大多数 PID 为 0。结构中只有少数 PID 与 ProcessHacker/TaskManager.

中列出的匹配

我不知道为什么 dwProcessId 字段包含 0,而显然这不是有效的 PID。提前谢谢你。

根据 QueryServiceStatusEx() 文档:

The process identifier returned in the SERVICE_STATUS_PROCESS structure is valid provided that the state of the service is one of SERVICE_RUNNING, SERVICE_PAUSE_PENDING, SERVICE_PAUSED, or SERVICE_CONTINUE_PENDING. If the service is in a SERVICE_START_PENDING or SERVICE_STOP_PENDING state, however, the process identifier may not be valid, and if the service is in the SERVICE_STOPPED state, it is never valid.

仅仅因为您可以获得服务的 SC_SERVICE 句柄并不能保证该服务实际上是 运行。 QueryServiceStatus/Ex()dwCurrentState 字段中告诉您服务是否 运行。

您也没有对第一个 QueryServiceStatusEx() 调用进行任何错误处理。

试试像这样的东西:

unsigned int get_svc_pid (SC_HANDLE svc)
{
    DWORD pid = 0;
    BYTE *buf = NULL;
    DWORD buf_size = 0;
    SERVICE_STATUS_PROCESS *svc_info = NULL;

    //determine svc_info size
    QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO, NULL, 0, &buf_size);
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    {
        fprintf(msglog, "ERR: QueryServiceStatusEx failed\nGLE: %u\n", GetLastError());
        return 0;
    }

    buf = malloc(buf_size);
    if (!buf)
    {
        fprintf(msglog, "ERR: malloc failed\nsize requested: %u\n", buf_size);
        return 0;
    }

    //get pid
    if (!QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO, buf, buf_size, &buf_size))
    {
        fprintf(msglog, "ERR: QueryServiceStatusEx failed\nGLE: %u\n", GetLastError());
    }
    else
    {
        svc_info = (SERVICE_STATUS_PROCESS*) buf;
        switch (svc_info->dwCurrentState)
        {
            case SERVICE_RUNNING:
            case SERVICE_PAUSE_PENDING:
            case SERVICE_PAUSED:
            case SERVICE_CONTINUE_PENDING:
                pid = svc_info->dwProcessId;
                break;
        }
    }

    free(buf);
    return pid;
}