LyingOnTheSky LyingOnTheSky - 1 month ago 15
C# Question

Why is the CommandLine property of a svchost.exe WIN32_Process null?

I try to silence system process that seem to go 100% sometimes with my program on; I don't mean to fix that system process but just to silence it. What I tried is:

ManagementObjectSearcher searcher = new ManagementObjectSearcher
( "select CommandLine,ProcessId from Win32_Process where Name='svchost.exe'" );
ManagementObjectCollection retObjectCollection = searcher.Get( );
foreach( ManagementObject retObject in retObjectCollection )
if( ( ( string )retObject[ "CommandLine" ] ).Contains( "-k NetworkService" ) ) { // <-- exception
var process = Process.GetProcessById( int.Parse( retObject[ "ProcessId" ].ToString( ) ) );
process.PriorityClass = ProcessPriorityClass.Idle;
process.ProcessorAffinity = new IntPtr( 1 );
}
retObjectCollection.Dispose( );


This code seem to raise null-exception.

When I add
retObject[ "CommandLine" ] != null &&
in the if's condition and debug it, all the values that produced from the expression
retObject[ "CommandLine" ]
are just
null
.

Wwhen I change
scvhost.exe
to
notepad.exe
they produce non-
null
values.

Why is that and how I can fix it to fetch system processes' commandline?

Answer

As you found out the CommandLine property on the Win32_Process class for svchost is null. That is because the svchost.exe is not started from the commandline (and that explains why searching for notepad.exe does work)

To get to the info you want to do dangerous things you'll need to query the Win32_Service as well.

using(var searcher = new ManagementObjectSearcher(
          "select CommandLine,ProcessId from Win32_Process where Name='svchost.exe'" ))
{
    using(var  retObjectCollection = searcher.Get( ))
    {
        foreach(var proc in retObjectCollection)
        {
            using(var procSearch = new ManagementObjectSearcher( 
                String.Format(
                    "select * from Win32_Service where ProcessId='{0}'",
                    proc["ProcessId"])))
            {
                using(var procResult = procSearch.Get( ))
                {
                    foreach(var svc in  procResult)
                    {
                        if( ((string)svc["PathName"]).Contains( "-k NetworkService" ))
                        {
                            // do nasty things with the info
                            svc.Dump();
                        }
                    }
                }
            }
        }
    }
}

I used the info from this Technet blog from Chris O'Prey to come up with this answer.

In theory you could do this in one wmi-query but WIN32_Service is slow to respond so it's better performance wise to first get the processes you're interested in and then query WIN32_Service.