2

I already searched here for an answer but I couldn't find any working code snippets or tips.

How do I get ProcessIds with a given CommandLine? I already got CommandLine by Pid with this method:

private IEnumerable<string> GetCommandLine(Process process)
{
    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id))
    using (ManagementObjectCollection objects = searcher.Get())
    {
        foreach (var element in objects)
            yield return element["CommandLine"]?.ToString();
    }
}

This works for getting CommandLine with given ProcessId. But I want the ProcessId with given CommandLine. I started a process which would have this CommandLine I'm searching for. This is my attempt:

private IEnumerable<int> GetIdsByCommandLine(string commandLine)
{
    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ProcessID FROM Win32_Process WHERE CommandLine = " + commandLine))
    using (ManagementObjectCollection objects = searcher.Get())
    {
        foreach (var element in objects)                
            yield return (int) element["ProcessId"];                
    }
}

But if I run this, it stops at beginning of the foreach-loop: "Query invalid" Can anybody help me with such a query to get ProcessId by CommandLine? Thanks in advance!

Edit: I need this for a process watchdog. I have 4 programs which are started with arguments. But there shouldn't be any instance of those programs before they start. So my attempt is to start each, getting the CommandLine (GetCommandLine above) of the process, killing the process, and then I want to search for processes with the same CommandLine to kill them. Only when this is done, I can start my 4 programs without them freaking around. That's why I need exactly a way to extract processIds by CommandLine.

Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
JayBeAl
  • 23
  • 5
  • Try taking a look at [a similar StackOverflow question](https://stackoverflow.com/questions/777548/how-do-i-determine-the-owner-of-a-process-in-c). – csharpforevermore Sep 12 '18 at 14:15
  • 1
    Is it as simple as the fact that you need to quote the string in your second example? In the first you didn't need quotes around the pid because its numeric. In the case of the command line though its a string so would presumably need to be quoted. I've never used this technology though so don't know for sure but given it is SQL like syntax I figure this is a reasonable guess.... – Chris Sep 12 '18 at 14:28
  • @Chris this sounds pausible, do u have an idea how this could look like? – JayBeAl Sep 12 '18 at 14:38
  • @csharpforevermore with Name and ProcessId there is no Problem. Those Queries work for me as well. But I need the procesid by commandline, look my edit on my post, that explains why. But thanks for answering. – JayBeAl Sep 12 '18 at 14:41
  • @JayBeAl: I'm not thinking of anything particularly complicated. If it was SQL I'd just add single quotes (ie `'`) before and after the string but as I say I don't know the details of this query language. Is it not documented anywhere? – Chris Sep 12 '18 at 14:43
  • I now tried something like that: "SELECT ProcessId FROM Win32_Process WHERE CommandLine = '{0}'", commandLine. Sadly it now says parameter invalid. Well i searched alot and found so many Queries with Names, ProcessIds but none with searching through commandlines. – JayBeAl Sep 12 '18 at 14:48
  • 1
    @JayBeAl: Well if all else fails you could potentially just remove the WHERE and then just do in memory checks using LINQ for what you want. Would make for easier debugging too. :) – Chris Sep 12 '18 at 15:07

2 Answers2

0

Maybe this can be useful to you.

using System.Diagnostics;
public class KillProcess
{
    [DllImport("user32.dll")]
    static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);


    Process _KillProcess(int Hwnd)
    {
        int id;
        GetWindowThreadProcessId(Hwnd, out id);

        Process _Process = Process.GetProcessById(id);

        _Process.Kill();
    }
}

Also, the other way is

System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");

foreach (System.Diagnostics.Process p in process)
{
    if (!string.IsNullOrEmpty(p.ProcessName))
    {
        try
        {
            p.Kill();
        }
        catch { }
    }
}
Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
prog2011
  • 51
  • 7
  • That doesn't look like it answers the question. OP wants to find process for a given command line, not name. – Rup Sep 12 '18 at 14:28
  • Yes @Rup is right, i can't work with the names, i need the processId according the commandline. But thanks – JayBeAl Sep 12 '18 at 14:35
0

Try using the scope parameter as well.

private IEnumerable<int> GetIdsByCommandLine(string commandLine)
{
    string queryString = "SELECT ProcessID FROM Win32_Process WHERE CommandLine = " + commandLine;
    string wmiScope = @"\\your_computer_name\root\cimv2";
    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiScope, queryString))
    using (ManagementObjectCollection objects = searcher.Get())
        foreach (ManagementBaseObject element in objects)
            yield return (int)element["ProcessId"];
}

Remember that the command line will vary depending on how the process was called so this is not a 100% reliable. I presume you are going to pass in the list of strings, one at a time, from GetCommandLine() into GetIdsByCommandLine()?

This is pointless because you can just change the queryString parameter above to

string queryString = "SELECT Name, CommandLine, ProcessId, Caption, ExecutablePath FROM Win32_Process";

as per this StackOverflow answer. This will allow you to get the Process Id AND the CommandLine at once, without having to enumerate the responses and make multiple calls to the database.

Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
csharpforevermore
  • 1,472
  • 15
  • 27
  • This and the 3rd Comment of @Chris on my post helped me. I now just get the objects with ProcessId and CommandLine and then use Linq to get what i want. Thanks! – JayBeAl Sep 13 '18 at 06:55