Behandelte Themen
Überblick
Beispiel 1: Ermitteln der Aliase von stop-processlokal laufende Prozesse aufrufen
Beispiel 1: lokale Prozesse ermitteln und mit Select-Object ausgeben
Beispiel 2: lokale Prozesse ermitteln und das Ergebnis mit dem Formatoperator formatieren
Beispiel 3: lokale Prozesse ermitteln und das Ergebnis mit dem Formatoperator, sowie Format-Table formatierenremote laufende Prozesse aufrufen
3.1Prozessabfrage mittels .Net bzw. Powershell cmdlet
Beispiel: remote Prozesse und das Ergebnis mit dem Formatoperator formatieren
3.2Prozessabfrage mittels WMI
Beispiel: remote Prozesse und das Ergebnis mit dem Formatoperator formatieren
3.3RemotePowershellSession
Beispiel: Prozessabfrage über PSRemoting
Ausgewählte Prozesse analysieren und bearbeiten
4.1ein Prozessobjekt erstellen
Beispiel 1: Ein Prozessobjekt mit .Net [system.diagnostics.process] bzw. mit dem cmdlet "get-process" erstellen
Beispiel 2: Ein Prozessobjekt mit der WMI-Klasse win32_process erstellen
4.2Prozesse neu starten
4.2.1Verwendung von start-Process aus den Communityextensions
4.2.2Verwendung einer .Net Klasse zum Starten eines Prozesses
Beispiel 1: Prozess neu starten mit [system.diagnostics.process]::start(<Name>)
Beispiel 2: Prozess neu starten mit [system.diagnostics.process]::start(<Name>) unter anderen Credentials
4.2.3Verwendung von start-process zum Starten eines Prozesses
Beispiel 1: Prozess einfach neu starten mit cmdlet start-process (native)
Beispiel 2: Prozess neu starten mit cmdlet start-process (native) mit den Parametern -wait und -WindowStyle
Beispiel 3: Onlinehilfe zu start-process (native) mit dem Parameter -verb
Beispiel 4: ermittlen der Verben von *.doc Dateien
Beispiel 5: Prozess neu starten mit cmdlet start-process (native) mit dem Parametern -verb
4.2.4Verwendung von WMI zum Starten eines Prozesses
Beispiel 1: einen RobocopyBefehl remote mit der Create-Methode von Win32_Process aufrufen
Beispiel 2: Weitere Optionen von Win32_Process ermitteln
Beispiel 3: einen RobocopyBefehl mit weiteren Optionen wie Username, Passwort, Impersonationlevel aufrufen
Beispiel 4: Cmdlet Invoke-WmiMethod (Alias: IWMI)
Schließen von Prozessen
5.1Prozesse beenden mit .Net Methoden
Beispiele: einige Methoden einen Prozess zu schliessen oder anzuhalten
5.2Prozesse beenden mit der WMI-Klasse win32_process
Beispiele: Beenden eines Prozesses mit der TerminateMethode
Beispiel: Beenden eines Prozesses mit Get-WmiObjectMonitoring von Prozessen
6.1 .NET-Klasse System.Diagnostics.Process und cmdlet get-process (mit Beispiel)
6.2.NET-Klasse System.Management.ManagementEventWatcher (mit Beispiel)
6.3cmdlet Register-WMIEvent (mit Beispiel) DLLs (Module) eines Prozesses bestimmen (mit Beispiel)
******************************************************************************************************
Tipp: In diesem Kapitel sind einige Links auf die MSDN-Seite enthalten. Mit dem FireFox-Browser (V 3.6) wird die Baumstruktur der MSDN sehr unschön dargestellt, das macht der Microsoft IE übersichtlicher.
1 Überblick
Prozesse lokal und remote auf einem oder mehreren Rechnern zu verwalten, zu überwachen, zu starten, zu stoppen und zu erforschen ist der Gegenstand dieses Kapitels.
In der Powershell2.0 stehen für diese Aufgaben folgende cmdlets bereit
Cmdlet | Alias | Synopsis |
Get-Process | gps, ps | Ruft die Prozesse ab, die auf dem lokalen Computer oder einem Remotecomputer ausgeführt werden. |
Start-Process Microsoft.PowerShell.Management\Start-Process PSCX\Start-Process | saps, start | Native-Powershell: Community-Extensions: Starts a new process. (local oder remote) |
Stop-Process | spps,kill | |
Wait-Process |
| Wartet, bis die Prozesse beendet wurden, bevor weitere Eingaben angenommen werden |
Debug-Process |
| Debuggt einen oder mehr Prozesse, die auf dem lokalen Computer ausgeführt werden. |
Get-WmiObject | GWMI | über die WMI-Klasse Win32_Process können Prozesse abgefragt werden. Mit den Eigenschaften create und terminate können Prozesse gestartet und beendet werden |
Invoke-WmiMethod | IWMI | eignet sich um Eigenschaften von WMI-Klassen aufzurufen. z.B. Create und Terminate der WMI-Klasse Win32_Process |
Beispiel 1: Ermitteln der Aliase von stop-process
get-alias -definition stop-process
#Ausgabe
CommandType Name
----------- ----
Alias kill
Alias spps
Hat man die CommunityExtensions (siehe Kapitel
2 Lokal laufende Prozesse aufrufen
Die aktuell laufenden Prozesse eines Systems lassen sich sehr einfach mit dem cmdlet "get-process" ermitteln. Die eigentliche Herausforderung besteht eher in der geeigneten Auswahl und passenden Formatierung der ermittelten Daten.
Beispiel 1: laufende Prozesse ermitteln und mit Select-Object ausgeben
# Bei diesem Beispiel werden die gewünschten Kriterien spaltenweise ausgegeben. Allerdings hat man nur wenig
# Einfluss auf Format oder Spaltenbreite
Get-Process | select-object name,starttime
# [system.diagnostics.process]::getprocesses() | select-object name,starttime
#gekürzte Ausgabe
Name StartTime
---- ---------
rdpclip 22.02.2010 10:22:12
conhost 22.02.2010 10:21:10
svchost 22.02.2010 10:20:55
vmicsvc 22.02.2010 10:21:00
conhost 05.03.2010 11:46:24
csrss 22.02.2010 10:21:29
svchost 22.02.2010 10:21:02
Beispiel 2: laufende Prozesse ermitteln und das Ergebnis mit dem Formatoperator formatieren
#Hier hat man schon etwas mehr Möglichkeiten über den Formatoperator die einzelnen Spalten zu formatieren.
get-process | foreach {"{0,-20} `t {1:d}" -f $_.name,$_.starttime}
#gekürzte Ausgabe
cmd 05.03.2010
conhost 22.02.2010
conhost 05.03.2010
conhost 05.03.2010
csrss 22.02.2010
csrss 22.02.2010
csrss 22.02.2010
Beispiel 3: laufende Prozesse eines Systems ermitteln und das Ergebnis mit dem Formatoperator, sowie Format-Table formatieren
#Hier hat man die meisten Möglichkeiten der Formatierung. Neben dem Formatoperator zur Wertformatierung kann man auch die Spaltenüberschriften, die Spaltenbreiten sowie die Ausrichtung der Spalten bestimmen
get-process | format-table `
@{Label="Prozessname";
Expression={"{0}" -f ($_.Name)}
width=15
Align="Left"
},
@{Label="Startzeit";
Expression={"{0:g}" -f ($_.starttime)} # g steht für Kombination aus Shortdate und Shorttime
Align="Left"
}
# Ausgabe gekürzt
Prozessname Startzeit
----------- ---------
cmd 05.03.2010 10:49
conhost 08.03.2010 13:23
conhost 22.02.2010 10:21
conhost 05.03.2010 11:46
conhost 05.03.2010 10:49
siehe Kapitel
3 Remote laufende Prozesse aufrufen
Die zugrunde liegende .Net Klasse von get-process kann auch remote verwendet werden. Allerdings fehlen dem gewonnenen Prozessobjekt eines Remoterechners der Inhalt einiger Eigenschaften wie beispielsweise der Inhalt der Eigenschaft „Starttime“
3.1 Prozessabfrage mittels .Net und Powershell cmdlet
Beispiel 1: remote Prozesse emitteln und das Ergebnis mit dem Formatoperator formatieren
$computername="DC1"
get-process –computername $computername | foreach {"{0,-12} `t {1:d} `t {2}" -f $_.name,$_.starttime, $_.workingset}
#gleichwertig.
[system.diagnostics.process]::getprocesses($computername) | foreach {"{0,-12} `t {1:d} `t {2}" -f $_.name,$_.starttime, $_.workingset}
#Ausgabe gekürzt
certsrv 15499264
cmd 2678784
conhost 2265088
conhost 3252224
bei Angabe eines Remoterechenrs werden Prozessname und Workingset zurückgegeben, aber nicht die Starttime. Ein Gegentest mit dem lokalen Rechnernamen liefert die Starttime aller Prozesse ohne Probleme
3.2 Prozessabfrage mittels WMI
Als Alternative zur Bestimmung aller Eigenschaften von der Prozesse von Remoterechnern bietet sich WMI an
Beispiel 1: remote Prozesse ermitteln und das Ergebnis mit dem Formatoperator formatieren
$p=get-wmiobject win32_process -computer DC1
$p | foreach{"{0,-20} {1,25} {2,23}" -f $_.name, $_.ConvertToDateTime($_.creationdate),$_.WorkingSetSize}
#oder auch analog zum 1.-ten Beispiel
#gwmi -computername DC1 win32_process | select-object name,{$_.ConvertToDateTime($_.CreationDate)}
#gwmi ist alias von get-wmiobject
#Ausgabe gekürzt
smss.exe 24.01.2011 13:44:23 409600
csrss.exe 24.01.2011 13:44:25 1724416
winlogon.exe 24.01.2011 13:44:28 8073216
services.exe 24.01.2011 13:44:28 7467008
Bei der Verwendung von WMI-Klassen sollte man zwei Dinge beachten:
a) Die Namen der Eigenschaften und Methoden der .Net Klasse Prozess
b) das Zeit bzw. das Datumsformat unter WMI ist relativ kryptisch. Eine einfache Methode, ein gewohntes Format zu erhalten geht über ConvertToDateTime (s.o.). Mit dem Formatoperator -f kann das erhaltene Objekt beliebig umformatiert werden.
Unter
3.3 RemotePowershellSession
Eine weitere -indirekte- Methode Prozesse remote zu überwachen, bringt Powershell V2.0 mit der Möglichkeit PS-Skripte komplett remote auszuführen mit.
Dazu muss auf dem Zielrechner einmalig das PSremoting mit
Enable-PSRemoting
zugelassen werden, wodurch dort der RMListener gestartet und die Firewall angepasst wird, sofern man die beiden folgenden Sicherheitsabfragen positiv bestätigt.
Auf den RemoteRechner -bei mir DC1- kann man nun vom lokalen Rechner aus eine PowershellSession öffnen, in der man uneingeschränkt arbeiten kann.
Enter-PSSession DC1 #etsn ist Alias von Enter-PSSession
[DC1]: PS C:\Users\User1\Documents> Get-Process #<-- Man beachte [DC1], dort wird der Befehl ausgeführt
#Ausgabe des RemoteRechners DC1 - gekürzt
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
276 39 13540 15136 106 1,50 1468 certsrv
20 4 2140 2616 38 0,05 3124 cmd
30 4 736 2212 25 0,00 2176 conhost
[DC1]: PS C:\Users\User1\Documents> Exit-PSSession #exsn ist Alias von Exit-PSSession
PS C:\>_ #<- zurück auf der lokalen Maschine
Viel genauer auf das PSRemoting gehe ich im Kapitel "
4 Ausgewählte Prozesse analysieren und bearbeiten
4.1 ein Prozessobjekt erstellen
Um einen bestimmten Prozess genauer anzusehen, zu verändern (z.B. Stoppen, Anhalten) etc. braucht man zuerst eine Objekt, dass den gewünschten Prozess repräsentiert (= Instanz) und dessen Methoden und Eigenschaften man benutzen kann.
Beispiel 1: Ein Prozessobjekt mit .Net [system.diagnostics.process] bzw. mit dem cmdlet "get-process" erstellen
$p=[system.diagnostics.process]::getprocessesbyname("notepad")#lokal
$p=[system.diagnostics.process]::getprocessesbyname("notepad","DC1") #remote auf DC!
#gleichwertig mit
$p=get-process –computername "DC1" notepad.exe
$p
#Ausgabe
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
63 7 1432 5204 74 0,08 2336 notepad
63 7 1432 5232 74 0,06 3796 notepad
65 7 1468 5716 74 0,38 3908 notepad
Beispiel 2: Ein Prozessobjekt mit der WMI-Klasse win32_process erstellen
#BeispielSkript über WMI
$select="select name,creationdate from win32_process where name='notepad.exe'"
$p=get-wmiobject -query $select -computername "DC1" | format-table name, {$_.ConvertToDateTime($_.CreationDate)}
$p
#Ausgabe
name $_.ConvertToDateTime($_.CreationDate)
---- -------------------------------------
notepad.exe 09.03.2010 22:39:13
notepad.exe 09.03.2010 22:39:20
notepad.exe 10.03.2010 11:44:36
4.2 Prozesse neu starten
4.2.1 Verwendung von start-Process aus den Communityextensions
Powershell V2.0 enthält das cmdlet start-process um Prozesse starten zu können. Die Communityextensions (siehe Kapitel
Ob man nun ein -oder beide cmdlets installiert hat, lässt sich z.B. mittels get-help ermitteln
Get-Help Start-Process
#mögliche Ausgabe, wenn die Communityextensions installiert sind
Name Category Synopsis
---- -------- --------
Start-Process Cmdlet PSCX Cmdlet: Starts a new process.
Start-Process Cmdlet Startet einen oder mehrere Prozesse auf dem lokalen Computer.
Wenn man die Communityextensions nutzt, würde ich um mögliche Versionskonflikte zu vermeiden beim Skripten die cmdlets inklusive den Namespaces verwenden. Dann erhält man wenigstens eine aussagekräftigere Fehlermeldung, wenn der PSCX-Namespace fehlt.
Microsoft.PowerShell.Management\Start-Process #natives cmdlet
# entspricht: [system.diagnostics.process]::start("<ProzssName")
PSCX\Start-Process #hinzuinstalliertes cmdlet der CommunityExtensions
get-help PSCX\Start-Process
#Ausgabe gekürzt
PS C:\Windows\System32\WindowsPowerShell\v1.0> get-help PSCX\Start-Process
NAME
Start-Process
ÜBERSICHT
PSCX Cmdlet: Starts a new process. #!!!!hier erkennt man die PSCX-Herkunft
SYNTAX
Start-Process [[-ScriptBlock] <ScriptBlock>] [-Boost] [-ComputerName <Str #!!Computername ist neu
4.2.2 Verwendung einer .Net Klasse zum Starten eines Prozesses
Beispiel 1: Prozess neu starten mit [system.diagnostics.process]::start(<Name>)
#Beispiele, um notepad zu starten
[system.diagnostics.process]::start("notepad")
[system.diagnostics.process]::start("notepad","c:\test.txt")
Beispiel 2: Prozess neu starten mit [system.diagnostics.process]::start(<Name>) unter anderen Credentials
$logon=get-credential #Credentials müssen eingegeben werden
[System.Diagnostics.Process]::Start("cmd.exe",$logon.username,$logon.password,"myMachine")
4.2.3 Verwendung von start-process zum Starten eines Prozesses
Beispiel 1: Prozess einfach neu starten mit cmdlet start-process (native)
start-process notepad C:\test.txt
#oder auch nur
notepad c:\test.txt
Beispiel 2: Prozess neu starten mit cmdlet start-process (native) mit den Parametern -wait und -WindowStyle
start-process -wait notepad C:\test.txt -WindowStyle Maximized
#-wait: Skript wartet bis der Notepad Prozess beendet wird
#-WindowsStyle Gültige Werte sind "Normal", "Hidden", "Minimized", "Maximized" siehe get-help start-process -detailed
Beispiel 3: Onlinehilfe zu start-process (native) mit dem Parameter -verb
Aus der Powershell Onlinehilfe zu start-process
-------------------------- BEISPIEL 2 --------------------------
C:\PS>start-process myfile.txt -workingdirectory "C:\PS-Test" -verb Print
Beschreibung
-----------
Dieser Befehl startet einen Prozess, der die Datei "C:\PS-#Test\MyFile.txt" druckt.
Interessant finde ich den Parameter -Verb, über den dieselbe Hilfe (etwas spärlich) aussagt
-Verb <string>
Gibt ein Verb an, das beim Starten des Prozesses verwendet werden soll, z. B. "Edit", "Open" oder "Print".
Eine erweiterte Hilfe findet man unter
The following table shows the verbs for some common process file types.
Extension | type Verbs |
.cmd | Edit, Open, Print, Runas |
.exe | Open, RunAs |
.txt | Open, Print, PrintTo |
.wav | Open, Play |
Beispiel 4: ermittlen der Verben von *.doc Dateien
Um die Verben weiterer Dateitypen wie Worddokumente zu erhalten, benötigt man die [System.Diagnostics.ProcessStartInfo] - Klasse
$startExe = new-object System.Diagnostics.ProcessStartInfo -args text.doc
$startexe.verbs
#Ausgabe
Edit
Open
OpenAsReadOnly
Print
Printto
Save As
Beispiel 5: Prozess neu starten mit cmdlet start-process (native) mit dem Parametern -verb
Wobei dann auch nicht alle Verben wirklich verwendet werden können
start-process "C:\Programme\Microsoft Office\OFFICE11\winword.exe" c:\temp\test.doc -verb openasreadonly
# bringt eine Fehlermeldung
start-process "C:\Programme\Microsoft Office\OFFICE11\winword.exe" c:\temp\test.doc -verb open
# öffnet die Worddatei
Falls jemand weitere Informationen und Einsatzmöglichkeiten über die verbs findet, würde ich mich sehr über Informationen freuen (Kontakt: siehe
4.2.4 Verwendung von WMI zum Starten eines Prozesses (SchemaQuery)
Um WMI-Methoden aufzurufen, gibt es wie so oft mehrere Ansätze. Ich will hier den Ansatz über die .Net-Klasse [System.Management.ManagementClass] mit dem zugehörigen Powershell TypeAccelerator [WmiClass] zeigen und danach über das cmdlet Invoke-WMIMethod mit dessen Alias iwmi.
Mit [WMIClass] erstellt man eine Instanz der Klasse selbst und wendet darauf eine Statische Methode wie "create" an.
Beispiel 1 : einen RobocopyBefehl remote mit der Create-Methode von Win32_Process aufrufen
$command="robocopy C:\temp\ C:\temp1 /s"
$Server="DC1"
$MC=[WmiClass] "\\$server\ROOT\cimv2:Win32_Process"
$StartupOptions=[WmiClass] "Win32_ProcessStartup"
$StartupOptions.PsBase.Properties["ShowWindow"].Value=0
$MC.create($command)
#[WmiClass] ist der Shortcut von [System.Management.ManagementClass]
- Im Kapitel
- Durch die das Setzen der StartupOption "ShowWindow=0" flackert kein Commandlinefenster auf
weitere Optionen unter MSDN:
- Möchte man die Robocopy-Robustheit in Powershell nachbauen, sind diese Links vielleicht interessant:
Beispiel 2: Weitere Optionen von Win32_Process ermitteln
$process = [WmiClass] "Win32_process"
$process.psbase.scope.options | get-member
#Ausgabe gekürzt
TypeName: System.Management.ConnectionOptions
Name MemberType Definition
---- ---------- ----------
Authentication Property System.Management.AuthenticationLevel Authentication {get;set;}
EnablePrivileges Property System.Boolean EnablePrivileges {get;set;}
Impersonation Property System.Management.ImpersonationLevel Impersonation {get;set;}
Password Property System.String Password {set;}
SecurePassword Property System.Security.SecureString SecurePassword {set;}
Timeout Property System.TimeSpan Timeout {get;set;}
Username Property System.String Username {get;set;}
Beispiel 3: Robocopy mit weiteren Optionen wie Username, Passwort, Impersonationlevel aufrufen
#Skript mit verschiedenen Optionen
#Vorlageskript: weblogs.asp.net/steveschofield/archive/2008/10/27/execute-a-command-with-powershell-using-win32-process.aspx
$cmd="robocopy C:\temp\ C:\temp1 /s"
$server="dc1" # für die lokale Maschine "."
$user="dom1\User1"
$password="HollaDieWaldFee1"
$process = [WMIClass]"\\$server\ROOT\cimv2:Win32_Process"
$process.psbase.Scope.Options.userName=$user
$process.psbase.Scope.Options.Password=$password
$process.psbase.Scope.Options.Impersonation = [System.Management.ImpersonationLevel]::Impersonate
$process.psbase.Scope.Options.Authentication = [System.Management.AuthenticationLevel]::PacketPrivacy
$process.Create($cmd)
# get process id and returnValue
$process.ProcessId
$process.ReturnValue
Ein weiteres Beispiel zur Verwendung von Robocopy zum Kopieren von ausgewählten Dateien findet ihr im Kapitel
Beispiel 4: Cmdlet Invoke-WmiMethod (Alias: IWMI)
Sehr elegant lässt sich das aufrufen eines Skripts auf einem Remotecomputer auch mit dem cmdlet Invoke-Wmi-Method lösen:
invoke-wmimethod -path win32_process -name create -argumentlist "robocopy c:\temp C:\temp1 /S" -computer dc1
4.2.5 Starten von mehreren Prozessen im Hintergrund
Mehrere Prozesse möglichst rasch nacheinander so zu starten, daß der nächste Prozess schon gestartet wurde, bevor der vorige beendet war, hat man zu Batchzeiten rudimentär mit den "Start"-Befehl erledigt.
Unter Powershell sind dafür die Job-cmdlets zuständig:
Beispiel 1: Anzeige der Job-cmdlets
get-command *-job
#Ausgabe
CommandType Name
----------- ----
Cmdlet Get-Job
Cmdlet Receive-Job
Cmdlet Remove-Job
Cmdlet Start-Job
Cmdlet Stop-Job
Cmdlet Wait-Job
Beispiel 2: Starten mehrerer Prozesse als Job
for($i=1;$i -le 20; $i++){
start-job -name $i -scriptblock {notepad c:\temp\big150000.txt}
}
"Skript ist durch, obwohl noch nicht alle NotepadProzesse fertig sind"
#Ausgabe
Skript ist durch, obwohl noch nicht alle NotepadProzesse fertig sind
5 Schließen von Prozessen
5.1 Prozesse beenden mit .Net Methoden
Beispiel 1: einige Methoden einen Prozess zu schliessen oder anzuhalten
$p=get-process notepad
$p.kill()
$p=get-process notepad
$p | foreach {stop-process ($_.id)}
$p=get-process notepad
$p | foreach {$_.kill()} #MSDN: Hält den zugeordneten Prozess sofort an.
$p=get-process notepad
$p | foreach {$_.close()} #MSDN: Gibt alle dieser Komponente zugeordneten Ressourcen frei, schliesst
# die Prozesse aber nicht
$p
$p=get-process notepad
$p | foreach {$_.closemainwindow()} #MSDN: Schließt einen Prozess mit einer Benutzeroberfläche, indem eine Meldung zum Schließen an das Hauptfenster gesendet wird.
Um an eine Anwendung vor dem Schliessen noch eine bestimmte Tastenkombination zu senden, bietet sich das "Windows Automation Snapin for Powershell" an.
5.2 Prozesse beenden mit der WMI-Klasse win32_process
Technet - ScriptingGuy!:
Beispiel1 : Beenden eines Prozesses mit der TerminateMethode
$cmd="notepad"
$server="dc1" # für die lokale Maschine "."
$processes=get-wmiobject -query ("SELECT * FROM Win32_Process WHERE Name = 'notepad.exe'") -computername $server
foreach($process in $processes){$process.terminate()} #terminate entspricht kill
#$processes | foreach{$_.terminate()} #gleichwertiger Befehl
# zum evtl. Troubleshooting helfen die im MSDN-Artikel genannten Return Values
Beispiel 2: Beenden eines Prozesses mit Get-WmiObject
Ein schönes Beispiel mit "Invoke-WMIMethod" Prozesse zu beenden, habe ich bei den ScriptingGuys gefunden
#Skript aus blogs.technet.com/heyscriptingguy/archive/2009/12/10/hey-scripting-guy-december-10-2009.aspx
Get-WmiObject -Class win32_process -Filter "name = 'notepad.exe'" |ForEach-Object { Invoke-WmiMethod -Path $_.__Path –Name Terminate }
6 Monitoring von Prozessen
Gelegentlich möchte man auf einem Rechner überwachen, ob ein bestimmter Prozess läuft und wann dieser gestoppt wurde. Dazu stehen einem aus .Net die Klasse [System.Management.ManagementEventWatcher] und aus WMI die Klasse SWBEMServices
6.1 .Net-Klasse System.Diagnostics.Process und cmdlet get-process
#Skript "beobachtet" den Prozess Notepad, schreibt nach dessen Beendigung einen Eintrag in eine Logdatei und startet den Prozss neu
$a = 1
$processname="notepad"
do {
$np = get-process $processname
# $np=[system.diagnostics.process]::getprocessesbyname("notepad")
$np.waitforexit()
"Notepad wurde am $(get-date) beendet" | out-file -Append c:\temp\notepad.log
start-process $processname
}
while ($a -eq 1)
Mit dem eben gezeigten Skript lässt sich ein Prozess überwachen, allerdings hat diese Methode eine Mankos. - eine Beendigung der Überwachung ist nur mit einem Abschiessen des Powershellskripts möglich- Das Skript ist nicht geeignet, wenn mehrere Instanzen eines Prozesses überwacht werden sollen- die Überwachung ist permanent und dadurch relativ rechenintensiv- die Überwachung eines Prozessstarts ist so nicht so einfach möglich
6.2 .Net-Klasse System.Management.ManagementEventWatcher
Flexibler als mit System.Diagnostics.Process bzw. get-process ist man mit der Klasse ManagementEventWatcher die .Net zum Monitoring vorsieht
Das folgende Skript protokolliert fortlaufend alle Prozesse, die geschlossen werden
#Skript muss gestartet werden und laufen
#http://blogs.technet.com/heyscriptingguy/archive/2007/03/26/how-can-i-use-windows-powershell-to-be-notified-when-an-application-terminates.aspx
$a = 0
$timespan = New-Object System.TimeSpan(0,0,10) # gibt in Stunden,Minuten,Sekunden an, wie oft der Monitor läuft
$scope = New-Object System.Management.ManagementScope("\\.\root\cimV2") #. steht für den lokalen Rechner
$query = New-Object System.Management.WQLEventQuery `
("__InstancedeletionEvent",$timespan, "TargetInstance ISA 'Win32_Process'" )
$watcher = New-Object System.Management.ManagementEventWatcher($scope,$query)
do
{
$b = $watcher.WaitForNextEvent()
$b.TargetInstance.Name
$b.TargetInstance.caption # Eigenschaftenn der WMI-Klasse: win32_process
$b.TargetInstance.executablepath
$b.TargetInstance.creationdate #Datum im WMI-Format
([WMI]'').ConvertToDateTime($b.TargetInstance.creationdate) #Datum im Langformat
"Eventdatum: $(get-date)"
}
while ($a -ne 1)
#Ausgabe
calc.exe
calc.exe
C:\Windows\system32\calc.exe
20100315154406.481302+060
Montag, 15. März 2010 15:44:06
Eventdatum 03/15/2010 15:44:09
Neben der Klasse __InstanceDeletionEvent gibt es noch das Gegenstück __InstanceCreationEvent um Erstellung von Prozessen zu beobachten.
6.3 cmdlet Register-WMIEvent
Eine andere, sehr elegante Möglichkeit den Start oder das Ende von Prozessen zu überwachen bietet Register-WMIEvent
Register-WMIEvent -query "Select * From __InstanceCreationEvent within 3 Where TargetInstance ISA 'Win32_Process'" -messageData "Prozess" -sourceIdentifier "SourceIdentifier1"
Dadurch werden Events untet dem SourceIdentifier1 (beliebiger Name) gesammelt und können mit Get-Event ausgelesen werden
Get-Event –sourceIdentifier "SourceIdentifier1"
#Ausgabe
ComputerName :
RunspaceId : 74868721-121e-4c91-af93-a4e7a55056b6
EventIdentifier : 1
Sender : System.Management.ManagementEventWatcher
SourceEventArgs : System.Management.EventArrivedEventArgs
SourceArgs : {System.Management.ManagementEventWatcher, System.Management.EventArrivedEventArgs}
SourceIdentifier : New Process
TimeGenerated : 15.03.2010 16:35:33
MessageData : A new process has started.
ComputerName :
RunspaceId : 74868721-121e-4c91-af93-a4e7a55056b6
EventIdentifier : 2
Sender : System.Management.ManagementEventWatcher
SourceEventArgs : System.Management.EventArrivedEventArgs
SourceArgs : {System.Management.ManagementEventWatcher, System.Management.EventArrivedEventArgs}
SourceIdentifier : New Process
TimeGenerated : 15.03.2010 16:35:52
MessageData : A new process has started.
Den SourceIdentifier kann man auch wieder deregistrieren mit
Unregister-Event "New Process"
Alle WMI SystemKlassen sind in der MSDN hier aufgeführt:
7 DLLs (Module) eines Prozesses bestimmen
Sieht man sich die Eigenschaften und Methoden eines Prozesses an z.B. mit "get-process notepad | get-member", so findet man die Eigenschaft Modules.
#Skript, welches die von einem Prozess geladenen DLLs anzeigt
$np=get-process notepad
$np | %{$_.modules} | sort-object size | ft ` #nur $np | %{$_.modules} liefert die Informationen ohne Formatierung
@{Label="ModuleName";
Expression={"{0}" -f ($_.ModuleName )}
width=25
Align="Left"
},
@{Label="Size(K)";
Expression={"{0}" -f ($_.Size)}
width=8
Align="Left"
},
@{Label="Product";
Expression={"{0}" -f ($_.product )}
width=45
Align="Left"
}
#Ausgabe
ModuleName Size(K)
---------- -------
VERSION.dll 48
LPK.dll 56
CRYPTBASE.dll 60
dwmapi.dll 96
sechost.dll 124
IMM32.DLL 184
Die unter Modules [System.Diagnostics.ProcessModule] zur Verfügung stehenden Eigenschaften und Methoden erhält man mit
$np=get-process notepad
$np | foreach {$_.modules} | get-member