Behandelte Themen

  1. Überblick
    Beispiel 1: Ermitteln der Aliase von stop-process

  2. lokal 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 formatieren

  3. remote laufende Prozesse aufrufen
    3.1 Prozessabfrage mittels .Net bzw. Powershell cmdlet
          Beispiel: remote Prozesse und das Ergebnis mit dem Formatoperator formatieren
    3.2 Prozessabfrage mittels WMI     
          Beispiel: remote Prozesse und das Ergebnis mit dem Formatoperator formatieren
    3.3 RemotePowershellSession
          Beispiel: Prozessabfrage über PSRemoting

  4. Ausgewählte Prozesse analysieren und bearbeiten
    4.1 ein 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.2 Prozesse neu starten     
          4.2.1 Verwendung von start-Process aus den Communityextensions         
          4.2.2 Verwendung 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.3 Verwendung 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.4  Verwendung 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)
                   
  5. Schließen von Prozessen
    5.1 Prozesse beenden mit .Net Methoden
          Beispiele: einige Methoden einen Prozess zu schliessen oder anzuhalten
    5.2 Prozesse beenden mit der WMI-Klasse win32_process
          Beispiele: Beenden eines Prozesses mit der TerminateMethode
          Beispiel: Beenden eines Prozesses mit Get-WmiObject

  6. Monitoring 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.3  cmdlet Register-WMIEvent (mit Beispiel)

  7. 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:
Startet einen oder mehrere Prozesse auf dem lokalen Computer.


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 Installation) installiert, so steht das start-process cmdlet mit Remotefähigkeit zur Verfügung.

 

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 Datei- und Textanalysen"Formatierung des Outputs" -> "Formatierte Tabellen"


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  MSDN: Process Properties stimmen nicht oder nur zufällig mit den Namen der Eigenschaften und Methoden der WMI-Klasse Win32-Process  MSDN: Win32_Process Class überein

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  "Formatierung des Outputs" -> "Formatierte Tabellen" gehe ich näher auf die Möglichkeiten an, den Output zu formatieren

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 "Powershell Remote" ein


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

 MSDN: Process.GetProcessesByName Method

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

 MSDN: Win32_Process Class

 

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 Installation) bringen ein zusätzliches cmdlet zum Starten von Prozessen zusätzlich mit Remotefähigkeit mit. Leider wurde auch dieses cmdlet Start-Process genannt.

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  Technet: Start-Process

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  Technet: Start-Process -> Example 6

$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 Home)

 

4.2.4 Verwendung von WMI zum Starten eines Prozesses (SchemaQuery)

 MSDN: Create Method of the Win32_Process Class (Link bitte im IE öffnen, nur dort wird die Baumstruktur der MSDN-Bibliothek korrekt dargestellt!)

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. Kapitel WMI  Abschnitt 2.6 SchemaQueries


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 Filesystem -> 2 Laufwerke, Ordner, Dateien und Freigaben (ohne ACL) findet ihr weitere praxisnahe Beispiele zu Robocopy und Powershell.

- Durch die das Setzen der StartupOption "ShowWindow=0" flackert kein Commandlinefenster auf
  weitere Optionen unter MSDN:  Win32_ProcessStartup class

- Möchte man  die Robocopy-Robustheit in Powershell nachbauen, sind diese Links vielleicht interessant:
 blog.usepowershell.com - Using the Sync Framework from PowerShell

 The ProwerShell Guy - PowerShell and Robocopy Part 4

 


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 Das Filesystem -> 2.2.2 Zeiteigenschaften (CreationTime, LastAccessTime, LastWriteTime) -> Beispiel 4d

 


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

 MSDN: Process Methoden

 

$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.  Codeplex: Windows Automation Snapin for PowerShell

 

5.2 Prozesse beenden mit der WMI-Klasse win32_process

Technet - ScriptingGuy!:  Use PowerShell and WMI to Terminate Multiple Processes

Beispiel1 : Beenden eines Prozesses mit der TerminateMethode

 Terminate Method of the Win32_Process Class

$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  MSDN: SWbemServices.ExecNotificationQueryAsync Method zur Verfügung. Die WMI-Klasse wird im Kapitel WMI, dort in Abschnitt 2.5 behandelt.

6.1 .Net-Klasse System.Diagnostics.Process und cmdlet get-process

 Technet - Scriptingguys: How Can I Use Windows PowerShell to Be Notified When an Application Terminates?

#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

 MSDN: __InstanceDeletionEvent Class
 MSDN: __InstanceCreationEvent Class

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

 Technet: WMI Event Monitoring

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:  MSDN: WMI System Classes

 

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