如何从 Visual C++ 获取特定的 windows 服务可执行文件路径

How to get the specific windows service executable file path from Visual C++

当我只知道服务名称时,如何从另一个程序中获取 运行 Windows 服务的可执行文件路径?

#include <Psapi.h>
#include <windows.h>
#pragma comment(lib, "psapi.lib")

int wmain() 
{
    //insert your service PID here instead of 404
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 404);
    if (!hProcess)
        return(0);

    wchar_t szBuffer[MAX_PATH];
    ZeroMemory(szBuffer, sizeof(szBuffer));
    DWORD dwSize = sizeof(szBuffer) / sizeof(szBuffer[0]) - 1;
    QueryFullProcessImageName(hProcess, 0, szBuffer, &dwSize);
    return(0);
}

您必须以提升的权限启动您的代码才能访问系统服务信息。否则 OpenProcess 将 return NULL 并且 GetLastError 将 return ERROR_ACCESS_DENIED 代码。

您还可以使用:

  1. GetProcessImageFileName获取系统native中的路径 格式;
  2. GetModuleFileNameEx 带有 NULL 模块句柄。

更新: 如果你只有服务名称,那么你必须使用不同的方法:

int wmain()
{
    LPQUERY_SERVICE_CONFIG lpsc;


    SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ);

    if (!hSCManager)
        return(0);

    SC_HANDLE hService = OpenService(hSCManager, L"Browser", SERVICE_QUERY_CONFIG); 

    if (!hService)
    {
        CloseServiceHandle(hSCManager);
        return(0);
    }


    DWORD dwBytesNeeded = 0, dwBufSize;
    if (!QueryServiceConfig(hService, NULL, 0, &dwBytesNeeded))
    {
        DWORD dwError = GetLastError();
        if (ERROR_INSUFFICIENT_BUFFER == dwError)
        {
            dwBufSize = dwBytesNeeded;
            lpsc = (LPQUERY_SERVICE_CONFIG)HeapAlloc(GetProcessHeap(), 0, dwBufSize);
        }
        else
        {
            CloseServiceHandle(hService);
            CloseServiceHandle(hSCManager);
            return(0);
        }
    }

    if (QueryServiceConfig(hService, lpsc, dwBufSize, &dwBytesNeeded))
    {
        //lpsc->lpBinaryPathName contains exe path
    }

    HeapFree(GetProcessHeap(), 0, lpsc);
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
    return(0);
}

使用QueryServiceConfig()QUERY_SERVICE_CONFIG::lpBinaryPathName 字段将报告用于 运行 服务的完整命令行。

例如:

struct SCHandle
{
private:
    SC_HANDLE hValue;
public:
    SCHandle(SC_HANDLE Value) : hValue(Value) {}
    ~SCHandle() { if (hValue != NULL) CloseServiceHandle(hValue); } 
    operator SC_HANDLE() { return hValue; } 
    bool operator!() const { return (hValue == NULL); } 
};

std::wstring GetServiceBinaryName(const std::wstring &ServiceName)
{
    SCHandle hSCManager(OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT));
    if (!hSCManager)
        return L"";

    SCHandle hService(OpenServiceW(hSCManager, ServiceName.c_str(), SERVICE_QUERY_CONFIG));
    if (!hService)
        return L"";

    std::vector<BYTE> buffer;
    DWORD dwBytesNeeded = sizeof(QUERY_SERVICE_CONFIGW);
    LPQUERY_SERVICE_CONFIGW pConfig;

    do
    {
        buffer.resize(dwBytesNeeded);
        pConfig = (LPQUERY_SERVICE_CONFIGW) &buffer[0];

        if (QueryServiceConfigW(hService, pConfig, buffer.size(), &dwBytesNeeded))
            return pConfig->lpBinaryPathName;
    }
    while (GetLastError() == ERROR_INSUFFICIENT_BUFFER);

    return L"";
}