获取Windows服务的PID

时间:2022-11-25 05:54:57

Could anyone help me to know how to get the PID of a Windows service?
I need to get the PID in order to run the following command:

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

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

3 个解决方案

#1


4  

Assuming you know the name of the EXE the service uses and there is exactly one of them:

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

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

The method Process.GetProcessesByName("yourservice.exe") returns an Array of Processes with your specified name, so in case you don't know how much of "yourservice.exe" runs simultaniously you might need a foreach loop.

方法Process.GetProcessesByName(“yourservice.exe”)返回一个具有指定名称的进程数组,因此,如果你不知道“yourservice.exe”运行了多少,你可能需要一个foreach循环。

#2


23  

What the other answers neglect is the fact that a single process can also host multiple, autonomous services. The multiple instances of the svchost.exe process, each hosting a couple of services, is the best example.

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

So in general, it is absolutely unsafe to try to kill an arbitrary service by killing it's hosting process (I assume that is what you attempt to do, since you refer to taskkill.exe). You might take down several unrelated services in the process.

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

If you do know that the service's process only hosts the service you care about, than you can choose the strategy as suggested by @M C in his/her answer.

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

Alternatively, you can also use the ServiceController class to open a handle to your service and then use it (via the ServiceHandle property) to P/Invoke the QueryServiceStatusEx function to find out the Process ID you want to know.

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

If you need more details, you should clarify what it is that you're actually trying to achieve. It is not clear from your question.

如果您需要更多细节,您应该澄清您实际上想要实现的目标。你的问题并不清楚。

Update Here is some code I ripped out of an existing project that should do what you want, given you have a ServiceController instance. _As said above, use with care!__

更新以下是我从现有项目中删除的一些代码,它们可以执行您想要的操作,因为您有一个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;
}

#3


1  

See this answer on a similar question: Finding out Windows service's running process name

在类似问题上查看此答案:查找Windows服务的运行进程名称

Using a WMI query you can -

使用WMI查询,您可以 -

Find all services related to a single exe (a single exe can host multiple services):

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

select Name from Win32_Service where ProcessId = 588

从Win32_Service中选择Name,其中ProcessId = 588

Or, to answer this question, you can get the PID of the process that a service is running in:

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

select ProcessId from Win32_Service where Name = 'wuauserv'

从Win32_Service中选择ProcessId,其中Name ='wuauserv'

#1


4  

Assuming you know the name of the EXE the service uses and there is exactly one of them:

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

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

The method Process.GetProcessesByName("yourservice.exe") returns an Array of Processes with your specified name, so in case you don't know how much of "yourservice.exe" runs simultaniously you might need a foreach loop.

方法Process.GetProcessesByName(“yourservice.exe”)返回一个具有指定名称的进程数组,因此,如果你不知道“yourservice.exe”运行了多少,你可能需要一个foreach循环。

#2


23  

What the other answers neglect is the fact that a single process can also host multiple, autonomous services. The multiple instances of the svchost.exe process, each hosting a couple of services, is the best example.

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

So in general, it is absolutely unsafe to try to kill an arbitrary service by killing it's hosting process (I assume that is what you attempt to do, since you refer to taskkill.exe). You might take down several unrelated services in the process.

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

If you do know that the service's process only hosts the service you care about, than you can choose the strategy as suggested by @M C in his/her answer.

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

Alternatively, you can also use the ServiceController class to open a handle to your service and then use it (via the ServiceHandle property) to P/Invoke the QueryServiceStatusEx function to find out the Process ID you want to know.

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

If you need more details, you should clarify what it is that you're actually trying to achieve. It is not clear from your question.

如果您需要更多细节,您应该澄清您实际上想要实现的目标。你的问题并不清楚。

Update Here is some code I ripped out of an existing project that should do what you want, given you have a ServiceController instance. _As said above, use with care!__

更新以下是我从现有项目中删除的一些代码,它们可以执行您想要的操作,因为您有一个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;
}

#3


1  

See this answer on a similar question: Finding out Windows service's running process name

在类似问题上查看此答案:查找Windows服务的运行进程名称

Using a WMI query you can -

使用WMI查询,您可以 -

Find all services related to a single exe (a single exe can host multiple services):

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

select Name from Win32_Service where ProcessId = 588

从Win32_Service中选择Name,其中ProcessId = 588

Or, to answer this question, you can get the PID of the process that a service is running in:

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

select ProcessId from Win32_Service where Name = 'wuauserv'

从Win32_Service中选择ProcessId,其中Name ='wuauserv'