获取Windows服务的PID

时间:2014-04-15 13:09:29

标签: c# .net windows-services

有谁能帮助我知道如何获得Windows服务的PID?
我需要获取PID才能运行以下命令:

Process.Start(new ProcessStartInfo 
    {
        Filename = "cmd.exe",
        CreateNoWindow = true,
        UseShellExecute = false,
        Arguments = string.Format("/c taskkill /pid {0} /f", pidnumber)
    });

3 个答案:

答案 0 :(得分:25)

其他答案忽略的是单个流程还可以托管多个自治服务svchost.exe进程的多个实例,每个实例都托管了几个服务,是最好的例子。

所以一般来说,通过杀死它的托管过程来尝试杀死任意服务是绝对不安全的(我认为这是你尝试做的事情,因为你引用了taskkill.exe)。您可以在此过程中删除几个不相关的服务。

如果您确实知道服务的流程只托管您关心的服务,那么您可以在他/她的答案中选择@M C建议的策略。

或者,您也可以使用ServiceController类打开服务句柄,然后使用它(通过ServiceHandle属性)到P/Invoke QueryServiceStatusEx函数找出您想知道的进程ID。

如果您需要更多详细信息,请说明您实际上正在尝试实现的内容。你的问题并不清楚。

更新以下是我从现有项目中删除的一些代码,它们可以执行您想要的操作,前提是您拥有ServiceController实例。 _如上所述,请小心使用!__

[StructLayout(LayoutKind.Sequential)]
internal sealed class SERVICE_STATUS_PROCESS
{
    [MarshalAs(UnmanagedType.U4)]
    public uint dwServiceType;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwCurrentState;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwControlsAccepted;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwWin32ExitCode;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwServiceSpecificExitCode;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwCheckPoint;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwWaitHint;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwProcessId;
    [MarshalAs(UnmanagedType.U4)]
    public uint dwServiceFlags;
}

internal const int ERROR_INSUFFICIENT_BUFFER = 0x7a;
internal const int SC_STATUS_PROCESS_INFO = 0;

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool QueryServiceStatusEx(SafeHandle hService, int infoLevel, IntPtr lpBuffer, uint cbBufSize, out uint pcbBytesNeeded);

public static int GetServiceProcessId(this ServiceController sc)
{
    if (sc == null)
        throw new ArgumentNullException("sc");

    IntPtr zero = IntPtr.Zero;

    try
    {
        UInt32 dwBytesNeeded;
        // Call once to figure the size of the output buffer.
        QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, 0, out dwBytesNeeded);
        if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
        {
            // Allocate required buffer and call again.
            zero = Marshal.AllocHGlobal((int)dwBytesNeeded);

            if (QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, dwBytesNeeded, out dwBytesNeeded))
            {
                var ssp = new SERVICE_STATUS_PROCESS();
                Marshal.PtrToStructure(zero, ssp);
                return (int)ssp.dwProcessId;
            }
        }
    }
    finally
    {
        if (zero != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(zero);
        }
    }
    return -1;
}

答案 1 :(得分:4)

假设您知道EXE的名称,该服务使用,其中只有一个:

int procID = Process.GetProcessesByName("yourservice")[0].Id;

方法Process.GetProcessesByName("yourservice")会返回一个包含您指定名称的进程数组,因此,如果您不知道有多少"yourservice.exe"同时运行,则可能需要一个foreach循环。

答案 2 :(得分:2)

在类似问题上查看此答案: Finding out Windows service's running process name

使用WMI查询,您可以 -

查找与单个exe相关的所有服务(单个exe可以托管多个服务):

select Name from Win32_Service where ProcessId = 588

或者,要回答这个问题,您可以获取正在运行服务的进程的PID:

select ProcessId from Win32_Service where Name = 'wuauserv'