2007-05-01

Setting the Priority of a Service Process via Script

Previously (here and here), I've written about isolating shared services so that they run in their own process, with a specific focus on the Windows Update Automatic Updates Service (wuauserv) that typically runs in the NETSVCS SVCHOST.EXE instance. One thing that can be done once this is accomplished is to lower the priority of the process so that when the service winds up consuming 100% of the CPU, the system doesn't become unresponsive.

Since we're dealing with a service, setting the priority of such a SVCHOST.EXE process can become problematic - the service may already be running, or, because it is a service, it is not started as non-service processes are, so one is not able to use START / [LOW NORMAL HIGH REALTIME ABOVENORMAL BELOWNORMAL] to impose a priority when the process starts. One can use a utility like Task Manager or Process Explorer to set the priority of a process on an ad hoc basis, but when the service restarts or the system reboots one has to remember to set the priority again.

Though not an ideal solution the following scripts (VBS using WMI, and PowerShell) can be used to set the priority of the SVCHOST.EXE instance hosting the isolated Windows Update Automatic Updates Service service to "below normal". Note that no check is done to ensure that the SVCHOST.EXE instance is only hosting one service - if wuauserv is found to be a service inside of the process, the priority is adjusted. Note also that no error handling is implemented.

I'll try to format the code so it looks nice, but I fear I will be limited...

Here's the code for the VBS / WMI script:



Const BELOW_NORMAL = 16384
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set colServices = objWMIService.ExecQuery( _
"SELECT * FROM Win32_Service where name='wuauserv'")
For Each oService in colServices
Set colProcesses = objWMIService.ExecQuery( _
"SELECT * FROM Win32_Process where ProcessId=" & oService.ProcessId )
For Each oProcess in colProcesses
oProcess.SetPriority(BELOW_NORMAL)
Next
Next


Here's the code for the PowerShell script:



(gps -id (get-wmiobject win32_service where {$_.name -eq "wuauserv"}).ProcessId).PriorityClass="BelowNormal"


The different values for the priority parameter of the SetPriority method of the Win32_Process WMI class can be found in the documentation for the SetPriority method.

The different values for the PriorityClass in the PowerShell script are "Normal", "Idle", "High", "RealTime", "BelowNormal", or "AboveNormal". Or, to get a list of the available options, one can use the following PowerShell command:



[ENUM]::getNames("System.Diagnostics.ProcessPriorityClass")

Once the script is in place and working, one can cause it to be invoked at will, or via scheduled task at specific times, or after logon, or any other way that one can get something to happen when Windows boots or a user logs on.


»

10 comments:

hi said...

How would I, if I want to, find which services are part of a particular svchost.exe? Can in be done in C#?

Thanks!

«/\/\Ø|ö±ò\/»®© said...

hi, hi.

Tasklist.exe with the /svc param can tell you, as can Process Explorer.

You can also inspect the registry to determine what services would load with what SVCHOST group (see "Troubleshooting Performance Issues with Automatic Updates" for more details.

As far as C# code, the following requires a reference to System.Management:
(The formatting will probably be all messed up since I'm restricted in the formatting I can do; if so, I'll see what I can do about it.)


using System;
using System.Management;

namespace MyGreenPaste
{
class Program
{
static void Main( string[] args )
{
if( args.GetLength( 0 ) <= 0 )
{
Console.WriteLine( "Usage: {0} pid",
System.IO.Path.GetFileName(
System.Diagnostics.Process.GetCurrentProcess().
MainModule.FileName ) );
Console.WriteLine( " where pid is the process id " +
"of a process hosting at least one service" );
return;
}

try
{
ManagementObjectSearcher mos =
new ManagementObjectSearcher( "root\\CIMV2",
string.Format( "SELECT * FROM Win32_Service " +
"where ProcessId={0}", args[0] ) );
foreach( ManagementObject result in mos.Get() )
{
Console.WriteLine( "{0} -> {1}", result["Name"],
result["DisplayName"] );
}
}
catch( ManagementException mex )
{
Console.WriteLine( "** Error querying WMI:\r\n{0}",
mex.Message );
}
}
}
}

Anonymous said...

VBS Script to change priority of svchost.exe(running under system account)process is not able to change priority. We have to run it under system account to be successfull. Is there a way how run VBS Script automatically under system account?
Thank you.

«/\/\Ø|ö±ò\/»®© said...

Hi, anonymous.
>> Is there a way how run VBS Script automatically under system account <<
You could use PsExec with its -s param to do so.


Another option may be to try putting this at the top of the script:
1) Set objLoc = createobject("wbemscripting.swbemlocator")
2) objLoc.Security_.privileges.addasstring "sedebugprivilege", true

Hope this helps!

--molotov

Anonymous said...

thanks It Helps.
Molotov what do you think about disadvantage by lowering priority of wuauserv which is controlled by antivir which run with high priority. Try to say it again using other words: How much it slow down system when process with high priority(antivir) have to wait for process with low priority(wuauserv). Thank you.

«/\/\Ø|ö±ò\/»®© said...

>> wuauserv which is controlled by antivir <<
Not sure what this means...

>> How much it slow down system when process with high priority(antivir) have to wait for process with low priority(wuauserv). <<
Well, the answer probably depends. If the Automatic Updates service is isolated into its own instance of SVCHOST.EXE, any potential impact would seem to be lessened. But perhaps I'm not thinking clearly - I can't conceive of a scenario where AV software would be waiting on Automatic Updates... Can you clarify what you mean?

Anonymous said...

>>scenario where AV software would be waiting on Automatic Updates... <<
sorry question is not if AV software would wait for Automatic Updates. Question is if AV software could be slowed down by controling process which have priority below normal.


For example "Automatic Updates" are installing KBxxxxxx, during installation of KBxxxxxx some processes take a lot of CPU (update.exe,svchost.exe,wuauclt.exe) all these processes have priority below normal. All these processes are chcecked by AV software, AV software check what they do which file are they handling and so on. But AV works with High priority. Could happend that AV software with High priority is controlling process whith low priority and because of controlled process with low priority working slow, AV software is also slowed down. Thanks a lot for your view.

«/\/\Ø|ö±ò\/»®© said...

>> But AV works with High priority <<
If the AV software is running with high priority, and if the AV software is truly "waiting", I can't see that there really should be any difference between the specified processes running at below normal, or normal priority. Process priority is not specific to these processes, so any difference that there may be would be felt anytime this type of scenario would arise.

The behavior or experience (in general) may vary from AV package to AV package. If a performance concern did present itself, of course one could revert any changes to see if they in fact played a role. Indeed the issue that prompted this article is itself a performance concern, so one may, in that scenario, need to choose between the lesser of two evils...

Unknown said...

dont stop suggesting people to use windows powershell.

1::itsa psuedo monopoly technique to force people to use windows piracy(theyve been stealing program and guis since DOS was around)
2::itsa DATAMINING PROGRAM that send YOUR CODE to microsoft. uninstall that trash

Unknown said...

excelent article. but its FAR simpler (and easier to read) to put the commands in autohotkey or batch scripting, or both :)

autohotkey
set,[windowdescriptor - pid - name - partialname - handle],{priority}[low - medium - high - Realtime],{threads}

batch
netservice {exactservicename} [priority] low medium high realtime

i prefer to use DELETE SERVICE. jsut watch out for the critical service cause when u reboot, THEY ARE GONE.

im having manic panick kernel issues with my windows xp(ancient 80 mb of ram) cause i set the default priotiy to low*then tried normal) for all processes through dimio' dtaskmanager software.

anyoen have the actual default priority list for windows xp services? i quite need them.