Get the PID of a Windows service
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.
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.
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.
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.
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!__
[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;
}
See this answer on a similar question: Finding out Windows service's running process name
Using a WMI query you can -
Find all services related to a single exe (a single exe can host multiple services):
select Name from Win32_Service where ProcessId = 588
Or, to answer this question, you can get the PID of the process that a service is running in:
select ProcessId from Win32_Service where Name = 'wuauserv'
Assuming you know the name of the EXE the service uses and there is exactly one of them:
int procID = Process.GetProcessesByName("yourservice")[0].Id;
The method Process.GetProcessesByName("yourservice")
returns an Array of Processes with your specified name, so in case you don't know how much of "yourservice.exe"
runs simultaneously you might need a foreach loop.