Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取Windows服务的PID_C#_.net_Windows Services - Fatal编程技术网

C# 获取Windows服务的PID

C# 获取Windows服务的PID,c#,.net,windows-services,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

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

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

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

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

方法
Process.getProcessByName(“yourservice”)
返回一个具有指定名称的进程数组,以防您不知道有多少
“yourservice.exe”
同时运行您可能需要一个foreach循环。

另一个答案忽略了一个事实,单个进程也可以承载多个自治服务。
svchost.exe
进程的多个实例(每个实例承载两个服务)就是最好的例子

因此,一般来说,试图通过终止任意服务的宿主进程来终止该服务是绝对不安全的(我假设这就是您试图做的,因为您引用了
taskkill.exe
)。在此过程中,您可能会删除几个不相关的服务

如果您确实知道服务的流程只承载您关心的服务,那么您可以选择@M C在其回答中建议的策略

或者,您也可以使用该类打开服务的句柄,然后(通过属性)将其用于函数以查找您想要知道的进程ID

如果你需要更多的细节,你应该澄清你真正想要实现的是什么。你的问题不清楚

Update这里是我从现有项目中提取的一些代码,如果您有一个
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;
}

请参见以下关于类似问题的答案:

使用WMI查询,您可以-

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

从Win32_服务中选择名称,其中ProcessId=588

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


select ProcessId from Win32\u Service where Name='wauserv'

您应该提到您可以有多个结果要验证我是否有正确的PID,我会像这样检查循环中的文件路径
if(processs[I].MainModule.FileName==myServiceExecutableFilePath)
可能有多个同名的EXE文件,并非所有这些都是您感兴趣的服务的服务流程。此外,如果您在未能正常停止服务进程后使用此命令终止服务进程,则如果进程在错误的时间死亡,它可能会异常失败。使用服务控制器,如您在回答中所建议的,这也是我的选择。这是最好的答案。调用
QueryServiceStatusEx
是否需要管理员权限?视情况而定。通常是的,但您也可以设置服务权限(针对特定服务)以允许以非管理员用户()的身份访问(查询这些服务的状态)。对于我来说,
Marshal.GetLastWin32Error()
返回零,但设置了
dwbytesRequired
。因此,我必须检查
错误\u缓冲区不足\u或为零。下次请不要忽略代码格式设置。正确格式化的代码有助于人们理解您的需求。即使Taskmanager没有在“流程”选项卡中显示您的服务。它仍然有一些可执行文件。谢谢你工作得很好