Per Powershell Skript die Priorität von Prozessen verändern

Vor zwei Jahren habe ich ein WSH Skript vorgestellt, mit dem man die Priorität von Prozessen verändert.

Das Skript hat selbst in seiner Kurzform 18 Zeilen, wobei man es sicher noch kürzen könnte.

War ich früher ein großer Fan von WSH gilt meine Vorliebe heute Powershell und den wunderbaren Powershell Einzeilern die so manchem Admin das Leben erleichtern.

So läßt sich das ganze Skript in Powershell in einer Zeile zusammenfassen:

gps <ProcessName>| % { $_.PriorityClass = "High" }

Dabei ist gps die Kurzform von get-process und % die Kurzform von foreach.

Also man könnte es auch so schreiben:

Get-Process <ProcessName>| foreach { $_.PriorityClass = "High" }

Am Beispiel von Internet Explorer würde das also so aussehen:

gps iexplore | % { $_.PriorityClass = "High" }

Falls man sich die Prozess Priority Klassen nicht merken kann, einfach einen ungültigen Parameter angeben, und Powershell liefert in der Fehlermeldung die Liste der richtigen Parameter:

image

Mögliche Enumerationswerte sind "Normal, Idle, High, RealTime, BelowNormal, AboveNormal"

Powershell Einzeiler: Einzelnen, internen SMTP Server zur Exchange Konfiguration hinzufügen

$a = (Get-TransportConfig).InternalSMTPServers ; $a += "192.168.10.5" ; Set-TransportConfig -InternalSMTPServers $a

Windows Services (Dienste) mittels Powershell starten

Habe mir in Windows Powershell einen netten Einzeiler zurechtgelegt, der mir automatisch alle Dienste startet, die eigentlich automatisch starten sollten, aber (aus welchem Grund auch immer) nicht laufen.
Auf einigen meiner Server kommt es immer mal wieder vor, das Services nicht laufen, die eigentlich laufen sollen. Mit diesem Powershell Skript ist das Problem schnell behoben:

Get-WmiObject Win32_Service | where {$_.StartMode -eq "Auto"} | where {$_.State -eq "Stopped"} | Start-Service

Podcatcher mittels Powershell und BITS

Das BITS (“Background Intelligent Transfer Service”) ist ein Windows Dienst der sich um den Download von (größeren) Dateien ressourcen und netzwerkschonend im Hintergrund kümmert. Da er als Service läuft und auch Resumes unterstützt, kann auch ein Reboot einem mit BITS initiierten Download nichts anhaben. Ursprünglich nur für Windows Updates gedacht, kann man BITS mit dem Tool bitsadmin.exe auch für andere/eigene Downloads nutzen.
Bitsadmin.exe bekommt man bei älteren Windows Versionen über die Windows Support Tools, ab Windows Vista ist es bereits enthalten.
Da bitsadmin.exe nicht besonders userfreundlich ist, verwende ich bget.cmd zur Steuerung von BITS download jobs.
Ich habe einige Video Podcasts (mit US Fernsehsendungen), die ich regelmäßig herunterladen möchte, und mit allen verfügbaren Podcatchern für Windows (inkl. iTunes) bin ich mehr als unzufrieden. Daher lag die Idee nahe, einen eigenen Podcatcher mit Powershell zu schreiben.

Nichts leichter als das!

Man nehme:

  • Powershell 1.0
  • bitsadmin.exe
  • bget.cmd (hier)

podcatcher.ps1

$feed=[xml](New-Object System.Net.WebClient).DownloadString("http://podcast.msnbc.com/audio/podcast/MSNBC-NN-NETCAST-M4V.xml")
foreach($i in $feed.rss.channel.item) {
    $url = New-Object System.Uri($i.enclosure.url)
   
$absURL = $url.AbsoluteUri   
    $filename = "D:\Videos\" + $url.Segments[-1]
    If ((Test-Path $filename) -eq $FALSE) 
    {
    bget """$absURL""" """$filename""" –b
    }
}

Zuerst hole ich mir das XML File des RSS Feed herunter. Dann loope ich durch alle items, und lasse mir die enclosure URLs zurückgeben. Als Objekt vom Typ System.Uri kann ich hier unter anderem auf die Parameter AbsoluteUri (ganze URL, bereits urlencoded, falls das im Feed nicht der Fall war) und segments[-1], welcher mir nur den Dateinamen zurückgibt, zugreifen.
Schließlich stelle ich noch sicher, dass das File im Zielpfad nicht existiert, und dann übergebe ich URL, Filename und den Batch Parameter “-b” an bget.
BITS erstellt das File im Zielordner erst, wenn es fertig heruntergeladen ist. Das ist auch praktisch im Vergleich zu anderen Podcatchern, so landen keine unfertigen Videos im Video-Ordner.
BITS und bget kümmern sich auch von selbst darum, dass ein File dass bereits heruntergeladen wird, nicht nochmal heruntergeladen wird (anhand der URL).
So muß ich podcatcher.ps1 nur mehr in der Aufgabenplanung regelmäßig ausführen, und ich habe einen perfekten podcatcher der absolut robust ist und mir nicht mehr ein Verzeichnis mit halbfertig heruntergeladenen Video Files hinterläßt, so wie seine Vorgänger.

Übrigens: Schön, wieder mal sagen zu können “In Windows 7 wird alles besser” – Genauer gesagt in PowerShell 2.0, das in Windows 7 und Windows Server 2008 R2 bereits enthalten sein wird. Da brauchen wir dann nämlich weder bitsadmin.exe noch bget.cmd sondern können BITS komplett mittels Powershell Cmdlets (z.B. 'New-FileTransfer') steuern. Mehr dazu hier -  die Syntax ist aber noch nicht ganz final. Wenn Powershell 2.0 final ist, werde ich dieses Skript umschreiben.

Per Skript die Priorität von Prozessen verändern

Die unglaubliche Macht von WSH (oder Powershell) in Kombination mit WMI ist mir schon länger bekannt. Ich möchte das für mich nutzen, um ein Skript zu schreiben, dass mir auf Klick (oder ereignisgesteuert) alle Prozesse mit einem bestimmten Namen beschleunigt oder abbremst, also die Priorität verändert.

Wie mache ich das? Mit einem Skript namens setprio.vbs, das zwei Parameter entgegennimmt, nämlich ‘Processname’ (in Kleinbuchstaben) und ‘DesiredPriority’
DesiredPriority kann einen dieser Werte haben:
IDLE|BELOW_NORMAL|NORMAL|ABOVE_NORMAL|HIGH_PRIORITY|REALTIME
In meinem Skript führt ein ungültiger Wert automatisch dazu, dass der Prozess auf ‘NORMAL’ zurückgesetzt wird.

Mit diesem Befehl werden also alle Internet Explorer Prozesse abgebremst:
cscript setprio.vbs iexplore.exe BELOW_NORMAL

image

Wofür kann man nun sowas in der Praxis wirklich brauchen?
Also: Man nehme an, man hat eine sehr große Musik- oder Videobibliothek umzuwandeln (wir sprechen von vielen Tagen, wenn nicht Wochen Rechenarbeit!), möchte aber z.B. unter Tags auf dem Rechner normal arbeiten können, dann muss man z.B. in der Früh nur diesen Befehl ausführen:
cscript setprio.vbs convertvideo.exe BELOW_NORMAL
Vor dem Schlafen gehen dann:
cscript setprio.vbs convertvideo.exe ABOVE_NORMAL
Natürlich kann man auch IDLE oder REALTIME nehmen, bzw. das ganze zeitgesteuert machen oder (unter Vista, Windows Server 2008 oder Windows 7) das ganze ereignisgesteuert machen.
Das Skript ist natürlich auch hervorragend etwa für einen (Home-)server oder ein Media Center geeignet, um die schwächeren Stunden oder die Nacht perfekt für Rechenaufgaben zu nützen. Ich werde mir das mittels Ereignissteuerung so konfigurieren, dass bestimmte Prozesse automatisch eine höhere oder sehr hohe Priority bekommen, wenn niemand vor dem Computer sitzt (=Bildschirm schwarz), und die Prozesse sofort in den Hintergrund fliegen, sobald der PC wieder benutzt wird.

Normalerweise schreibe ich gerne kurze, lesbare Skripts, ich habe hier bewußt etwas ausgefeiltere Rückmeldungen und Fehlerbehandlungen eingebaut. Mit Powershell wäre das natürlich sogar als Einzeiler realisierbar gewesen. Aber Powershell ist halt noch nicht auf jedem Windows PC standardmäßig installiert, daher bevorzuge ich zur Zeit (von Exchange 2007 Servern abgesehen) noch WSH/VBScript:

set args = WScript.Arguments
num = args.Count

'Error handling if no command line parameters given
if num < 2 then
   WScript.Echo "No command line parameters!"
   WScript.Echo "Syntax: cscript setprio.vbs ProcessName DesiredPriority"
   WScript.Echo "DesiredPriority can be: "
   WScript.Echo "IDLE|BELOW_NORMAL|NORMAL|ABOVE_NORMAL|HIGH_PRIORITY|REALTIME"
   WScript.Quit 1
end if

ProcessName   =     args.Item(0)
DesiredPriority =    args.Item(1)

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")

'Here all Processes will be found,
'
that contain the ProcessName and the Sub SetPID will be called
For Each objItem in colItems
    If InStr(lcase(objItem.Name), ProcessName) Then
        '    Use objItem.CommandLine instead of objItem.Name
        '    if you want to match a string as part of the
        '    full commandline for the process!
    Call SetPID (objItem.ProcessID, GetPriorityID (DesiredPriority))
    End If
Next

'Here the Processes will be set to the desired priority
Sub SetPID (intPID, intPriority)

    set objWMIProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process.Handle='" & intPID & "'")
    intErrorCode = objWMIProcess.SetPriority(intPriority)
    if intRC = 0 Then
       Wscript.Echo "Successfully set priority for process " & objWMIProcess.Name & " (ID: " & intPID & ") to " & GetPriorityName(intPriority)
    else
       Wscript.Echo "Error: '" & intErrorCode & "' setting priority for process " & objWMIProcess.Name & "(ID: " & intPID & ") to " & GetPriorityName(intPriority)
    end if
       Wscript.Echo "(Command: '" & objItem.CommandLine & "')"
       Wscript.Echo vbcrLF
End Sub

'These two functions aren't really necessary, they just translate
'
the more readable priority names into the numbers
'required by objWMIProcess.SetPriority

Function GetPriorityName (intPriority)
    Select Case intPriority
        Case 32:     GetPriorityName = "NORMAL"
        Case 64:     GetPriorityName = "IDLE"
        Case 128:     GetPriorityName = "HIGH_PRIORITY"
        Case 256:     GetPriorityName = "REALTIME"
        Case 16384:     GetPriorityName = "BELOW_NORMAL"
        Case 32768:     GetPriorityName = "ABOVE_NORMAL"
    End Select
End Function

Function GetPriorityID (strPriorityName)
    Select Case strPriorityName
        Case "NORMAL":        GetPriorityID = 32
        Case "IDLE":        GetPriorityID = 64
        Case "HIGH_PRIORITY":    GetPriorityID = 128
        Case "REALTIME":    GetPriorityID = 256
        Case "BELOW_NORMAL":    GetPriorityID = 16384
        Case "ABOVE_NORMAL":    GetPriorityID = 32768
        'Invalid Priorityname resets Priority to 'NORMAL'
        Case ELSE:        GetPriorityID = 32
    End Select
End Function

Hier noch eine verkürzte Version davon, nur um zu zeigen, dass es natürlich auch kürzer geht, wenn man etwa die Parameter direkt in’s Skript gibt, und nicht ganz so viele Ausgaben macht:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")

For Each objItem in colItems
    If InStr(lcase(objItem.Name), "notepad.exe") Then
    Call SetPID (objItem.ProcessID, 16384)
    End If
Next

Sub SetPID (intPID, intPriority)

    set objWMIProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process.Handle='" & intPID & "'")
    intErrorCode = objWMIProcess.SetPriority(intPriority)
    if intRC = 0 Then
       Wscript.Echo "Successfully set priority for process " & objWMIProcess.Name & " (ID: " & intPID & ")"
    else
       Wscript.Echo "Error: '" & intErrorCode & "' setting priority for process " & objWMIProcess.Name & "(ID: " & intPID & ")"
    end if
End Sub

Weitere Informationen: Das Einrichten von ereignisgesteuerten Aufgaben erkläre ich in einem anderen Zusammenhang in diesem Beitrag.

Dell Seriennummer auslesen

Dieses nette kleine Skript liest die Seriennummer von Dell Servern (aber auch PCs und Laptops) aus:

serial.vbs

Set wmiobj = GetObject("winmgmts://localhost/root/cimv2:Win32_BIOS")
For each ver in wmiobj.Instances_
MsgBox ver.SerialNumber
Next

Auf einem Dell Server und auf einem Dell Laptop getestet, sollte aber auch bei anderen Marken funktionieren, die Ihre Seriennummer im Bios hinterlegen.

Facebook

Letzte Tweets

Twitter Mai 26, 23:39
Gelbe Engel! Danke!

Twitter Mai 18, 21:34
Finland was terrible. #Eurovision

Twitter Mai 17, 12:49
just blogged Ist das Surface Pro teuer? – Ein Fact-Check: Gestern wurde angekündigt, dass das Surface Pro in D... http://t.co/PhW7qzhkUq

Folge mir auf Twitter!

Über den Autor

MCTS

Christian Haberl Christian Haberl ist seit mehr als 10 Jahren als EDV Berater, Vortragender und Trainer tätig. Er kann sich nicht für ein Spezialgebiet entscheiden, drum heißt dieser Blog auch "Kraut & Rüben Blog" - Unter seine Interessen fallen Web-Entwicklung auf ASP.NET Basis, Information Worker & Productivity Technologien (Windows, Office), Server (Windows Server, Small Business, Virtualisierung, Exchange), Scripting, Spam Filtering/Security und Digital Home. Christian Haberl ist auch einer der führenden Produktspezialisten für Windows Media Center und Windows Home Server und ist Direktor des ClubDigitalHome.
Im Jahr 2008 hat Christian Haberl über 200 Vorträge und Schulungen durchgeführt.
Im Frühjahr 2009 wurde Christian Haberl von Microsoft Österreich zum "Influencer" ernannt, weiters wurde er Microsoft Certified Technology Specialist / Microsoft Certified Connected Home Integrator sowie Microsoft Certified Consumer Sales Specialist.

Month List

Netzwerk Management

Bandwidth

RecentComments

Comment RSS