4 PowershellRemote in allen Variationen

In der Powershell kann man auf mehrere Arten Remoteverbindungen zwischen Rechnern aufbauen und nutzen. In diesem Kapitel stelle ich einige Varianten davon vor.

4.1 Alternativen zu WS-MAN/ WinRM

Wie in der Kapitel 0 Einleitung schon kurz ausgeführt, versteht Microsoft unter PowershellRemoting in erster Linie den Einsatz von WinRM mit den zugehörigen Powershellbefehlen.
Neben der Möglichkeit über den WSMAN eine Remoteverbindung aufzubauen, gibt es aber noch weitere Möglichkeiten:


a) cmdlets mit dem -computername Parameter

Laut about_remote besitzen folgende cmdlets den Parameter "Computername"

 Clear-EventLog Limit-EventLog Get-Counter New-EventLog Get-EventLog Remove-EventLog Get-HotFix Restart-Computer Get-Process Show-EventLog Get-Service Show-Service Get-WinEvent Stop-Computer Get-WmiObject Write-EventLog 

Beispiel 1: Abrufen aller Processe von einem RemoteComputer

Get-Process -computername dc1.dom1.intern 

Diese cmdlets können ohne weitere Vorbereitung alleine durch die Benutzung des Positionsparameters -computername remote benutzt werden. Die Kommunikation erfolgt über den Port 445 (microsoft-ds). 


b) WMI

Get-WmiObject -computername

WMI habe ich in Grundlagen -> Automation Interfaces -> WMI bereits ausführlich behandelt.  


Beispiel 2: Abrufen aller Processe von einem RemoteComputer mittels WMI

Get-WmiObject Win32_Service -computername 192.168.178.6

WMI besitzt den Positionsparameter -computername nativ und kann damit ebenfalls nativ remote eingesetzt werden. Die Kommunikation wird über Port 135 aufgebaut und läuft anschliessend über Highports.

 

c) interaktive Session mit psexec von Sysinternals aufbauen

Weit verbreitet ist das kostenlose psexec-Tool. Der große Vorteil dieses Tools ist, dass man ohne Konfiguration des Zielrechners eine interaktive CommanlineSession zu diesem aufbauen kann. Für Powershell-Remoting muss hingegen zumindest ein Listener konfiguriert werden.

Beispiel 3: Sicherheitsloch in psexec
Bei aller Bewunderung für den Programmierer Mark Russinovich steckt in diesem Tool ein ordentliches Sicherheitsleck (psexec Version 1.98)

Verbindet man sich in der Windows Commandshell damit auf einen anderen Rechner

psexec \\192.168.129.126 cmd.exe -u dom1\karlnapf DemoPW123
PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com


Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. Alle Rechte vorbehalten.

C:\Windows\system32>

und snifft mit Wireshark den Verbindungsaufbau mit, so sieht man die unverschlüsselte Kommunikation und die    unverschlüsselten Credentials.
Die Erklärung zu Option "-p Specifies optional password for user name. If you omit this you will be prompted to enter a hidden password." täuscht nur eine nicht vorhandene Sicherheit vor. Eine SSL-Option, sowie einen deutlichen Hinweis würde ich erwarten.

Die Kommunikation erfolgt über den Port 445 (microsoft-ds).

Zumindest ist eine unverschlüsselte Übertragung von Credentials im Jahr 2011 nicht mehr zeitgemäss. 

4.2 Sitzungskonfiguration / Sessionconfiguration

KURZBESCHREIBUNG
Beschreibt Sitzungskonfigurationen, die bestimmen, welche Benutzer eine Remoteverbindung mit dem Computer herstellen und welche Befehle diese Benutzer ausführen können.

aus: Technet: about_Session_Configurations

Neben dieser konzeptionellen Hilfe gibt es noch folgende cmdlets, um Sessions zu konfigurieren

Beispiel 1: Anzeige der cmdlets zur Verwaltung einer SessionConfiguration

Get-Help PsSessionConfiguration
Name                              Category  Synopsis
----                              --------  --------
Register-PSSessionConfiguration   Cmdlet    Erstellt und registriert eine neue Sitzungskonfiguration.
Unregister-PSSessionConfiguration Cmdlet    Löscht eine registrierte Sitzungskonfiguration vom Compute
Get-PSSessionConfiguration        Cmdlet    Ruft die registrierten Sitzungskonfigurationen auf dem Com
Set-PSSessionConfiguration        Cmdlet    Ändert die Eigenschaften einer registrierten Sitzungskonfi
Enable-PSSessionConfiguration     Cmdlet    Aktiviert die Sitzungskonfigurationen auf dem lokalen Comp
Disable-PSSessionConfiguration    Cmdlet    Verweigert den Zugriff auf die Sitzungskonfigurationen auf

 

Beispiel 2: Abfragen der vorhandenen SessionConfigurations auf dem lokalen Computer mit get-pssessionconfiguration

Technet: Get-PsSessionConfiguration

get-pssessionconfiguration | format-list -property name, permission
#Ausgabe auf 32 Bit OS
Name       : Microsoft.PowerShell
Permission : Jeder AccessDenied
#Ausgabe auf 64 Bit OS
Name       : microsoft.powershell
Permission : VORDEFINIERT\Administratoren AccessAllowed

Name       : Microsoft.PowerShell32
Permission : VORDEFINIERT\Administratoren AccessAllowed

- Die Sitzungskonfiguration "microsoft.powershell" und "Microsoft.PowerShell32" werden integrierte Sessioncinfigurations genannt. Diese werden von Powershell default verwendet, wenn die cmdlets  (New-PSSession, Enter-PSSession, Invoke-Command ) zum Aufbau einer Session ohne den Positionsparameter "-Configurationname" aufgerufen werden.
Auf 64-Bit Betriebssystemen existiert je eine Konfiguration für 32-Bit (Microsoft.PowerShell32) und eine Konfiguration für 64-bit (microsoft.powershell), auf 32-Bit Systemen existiert nur die microsoft.powershell

- auf die integrierte Sitzungskonfiguration können nur Mitglieder der Gruppe "Administratoren" zugreifen. Das bedeutet, nicht-Administratoren können keine Powershellsession Remote eröffnen.

- Genauer auf die Abragemöglichekeiten vorhandener Sessionconfigurationen gehe ich im Kapitel 4.2.2 Sitzungskonfigurationen auslesen ein. Unter anderem zeige ich dort, wie man Sessionconfigurationen remote abfragen kann und wie und wo sie gespeichert sind.

 

4.2.1 Erstellen und Verwenden einer neuen SessionConfiguration

Beispiel 1: Erstellen einer neuen Sessionconfiguration mit einem Startupscript

In ein Startupscript kann man all die Dinge hineinstecken, die man für lokale User in lokalen Profilen (siehe Profile/ Aliase -> Kapitel 1.3 Beispiele für Profile) bereitstellt, wie Aliase und Funktionen. Ebenso können hier auch Snap-ins und Module bereitgestellt werden, so dass diese nicht jedesmal extra nachgeladen werden brauchen, wie das in den Beispielen von  Kapitel 4.5.1 Import-PSSession für implizite Sessions geschieht.

Ich habe dieses Beispiel, das die Funktionsweise einer SessionConfiguration verdeutlichen soll, der Übersicht halber in einzelne Schritte untergeteilt, :

Vorbereitungsschritt 0) Anlage des Startupscripts c:\scripts\test1.ps1 
Um das Beispiel funktionsfähig zu sehen, legt bitte vorher unter C:\scripts\ das PS-StartupScript test1.ps1 mit diesem Inhalt ab.

Write-Host "hellgrüner Hintergrund ist MegaIN!"
$win = (Get-Host).UI.RawUI
$win.BackgroundColor = "green"


Schritt 1) Neuregistrierug der SessionConfiguration "Config-Session1"

Register-PSSessionConfiguration -Name "Config-Session1" -StartupScript C:\scripts\test1.ps1 -force
#Ausgabe 1)

   WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin

Name                      Type                 Keys
----                      ----                 ----
Config-Session1           Container            {Name=Config-Session1}

Anmerkung zu 1)
Technet: Register-PSSessionConfiguration
Die erstellte Sessionconfiguration bleibt auch nach einem Reboot solange erhalten, bis sie mit dem cmdlet "Unregister-PSSessionConfiguration" wieder entfernt wird. (siehe den letzten Teil 4a dieses Beispiels)


Schritt 2) Abfrage aller SessionConfigurations auf dem lokalen Rechner 

Get-PsSessionConfiguration
#Ausgabe 2)

Name                      PSVersion  StartupScript        Permission
----                      ---------  -------------        ----------
Config-Session1           2.0        C:\scripts\test1.ps1
microsoft.powershell      2.0                             VORDEFINIERT\Administratoren Acc...
Microsoft.PowerShell32    2.0                             VORDEFINIERT\Administratoren Acc...

Anmerkung zu Schritt 2)
Technet: get-pssessionconfiguration
"Config-Session1" ist neu dazugekommen. Die beiden Microsoft.Powershell-ConfigurationSessions sind die integrierten (=default) Configurations (siehe Beispiel 2 in Kapitel 4.2)


Schritt 3) Betreten einer Session. Dies kann auf dem lokalen, oder auch von einem RemoteRechner -dann mit dem Positionsparameter computername" aus geschehen

Enter-PsSession -computername dom1win7 -configurationname config-session1
#Ausgabe 3)
hellgrüner Hintergrund ist MegaIN!
hostname
Dom1Win7
[dom1win7]: PS C:\Users\KarlNapf.DOM1\Documents>
Exit-PsSession

Anmerkung zu Schritt 3)
Die Ausgabe erfolgt aufgrund des Startupscript in 0) auf giftgrünem Hintergrund, der auch nach dem Verlassen der Session mit exit-pssession bestehen bleibt.
(Leider kann ich in diesem CMS keine Farben darstellen).


Schritt 4a) Entfernen der Sessionconfiguraion

Unregister-PSSessionConfiguration -Name "Config-Session1" -force

Anmerkung zu Schritt 4a)
Technet: Unregister-PSSessionConfigruation
Mit diesem Befehl wird "Config-Session1" wieder entfernt. Der Positionsparameter "-force" unterbindet zwei Sicherheitsabfragen, die sonst extra bestätigt werden müssen.


Schritt 4b) Disablen der Sessionconfiguraion

Disable-PSSessionConfiguration -Name "Config-Session1" -force

Anmerkung zu Schritt 4b)
Technet: Disable-PSSessionConfiguration
Statt eine SessionConfiguration wieder komplett zu entfernen, kann man die Sessionconfiguration auch nur disablen. Dadurch wird ihr Securitydescriptor so verändert, daß sie nicht mehr in einer Session geladen, aber noch verändert, angesehen und wieder reaktiviert werden kann.

 

4.2.2 Sitzungskonfigurationen auslesen

Technet: about_Session_Configurations

Im einleitenden Kapitel 4.2 Sitzungskonfiguration / Sessionconfiguration habe ich im Beispiel 2 gezeigt, wie die vorhandene lokale Sessionconfiguration mit dem cmdlet "get-pssessionconfiguration" angezeigt werden kann.
In diesem Kapitel gehe ich, wie dort angekündigt, genauer auf die Abfrage von Sessionconfigurationen ein. 


Beispiel 1: Abfrage der vorhandenen Sessionkonfigurationen auf dem lokalen Computer mit dem WS-Verwaltungsanbieter
(aus dem eben genannten Technet Artikel "about_Session_Configurations". Dort sind auch noch weitere Details beschrieben)

dir wsman:\localhost\plugin\*
#Ausgabe
   WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin

Name                      Type                 Keys
----                      ----                 ----
Config-Session1           Container            {Name=Config-Session1}
Config-Session2           Container            {Name=Config-Session2}
Config-Session3           Container            {Name=Config-Session3}
Event Forwarding Plugin   Container            {Name=Event Forwarding Plugin}
microsoft.powershell      Container            {Name=microsoft.powershell}
Microsoft.PowerShell32    Container            {Name=Microsoft.PowerShell32}
WMI Provider              Container            {Name=WMI Provider}

Die SessionConfigurations sind in der Registry unter
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin\ gespeichert.

Ansehen kann man eine Sessionkonfiguration direkt, wenn man den RegistryWert ConfigXML nach notepad kopiert, die Datei mit der Endung *.xml abspeichert und in einem Webbrowser anzeigen lässt. In den nächsten beiden Bildern ist dieser Vorgang dargestellt.


Beispiel 2: Detaillierte Information einer Sessionconfiguration mit get-pssessionconfiguration abfragen

Die xml-Informationen lassen sich natürlich auch per Skript abfragen, wie unter Beispiel 3 unter Technet: get-pssessionconfiguration beschrieben ist

Get-PSSessionConfiguration -name microsoft.powershell | format-list -property *
#Ausgabe gekürzt
... Uri : schemas.microsoft.com/powershell/microsoft.powershell SecurityDescriptorSddl : O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD) ExactMatch : False ...

Beispiel 3: Abfrage der vorhandenen Sessionkonfigurationen auf einem RemoteComputer mit dem WS-Verwaltungsanbieter

dir wsman:\dc1.dom1.intern\plugin\*
#Ausgabe

   WSManConfig: Microsoft.WSMan.Management\WSMan::dc1.dom1.intern\Plugin

Name                      Type                 Keys
----                      ----                 ----
Event Forwarding Plugin   Container            {Name=Event Forwarding Plugin}
microsoft.powershell      Container            {Name=microsoft.powershell}
Microsoft.PowerShell32    Container            {Name=Microsoft.PowerShell32}
microsoft.ServerManager   Container            {Name=microsoft.ServerManager}
SEL Plugin                Container            {Name=SEL Plugin}
WMI Provider              Container            {Name=WMI Provider}

Vergleiche auch das Beispiel in Technet: about_Session_Configurations unter der Überschrft "Anzeigen von Sitzungskonfigurationen auf einem Remotecomputer".

4.2.3 Einschränken der verfügbaren cmdlets

Eine weitere faszinierende Möglichkeit des Powershellremotings liegt darin, durch Sessionconfigurations nur einen vordefinierte Satz an cmdlets bereitzustellen.
Damit kann man Hilfsrollen die Möglichkeit einräumen, nur bestimmte Aktionen mittels Powershell auf einem Remoterechner ausführen zu dürfen.
Die Rechte auf Sessionconfigurations können dann weiter auf bestimmte User oder Gruppen beschränkt werden. Im nächsten Kapitel 4.2.4 ist beschrieben, wie man den Securitydescriptor konfigurieren kann. Hier in 4.2.3 gehts erstmal darum, die erlaubten cmdlets festzulegen.


Beispiel 1: die verfügbaren cmdlets mit einer SessionConfiguration so beschränken, dass Accounts angesehen, aktiviert und deaktiviert werden können.

Vorbereitungsschritt 0: Anlage des Startupscripts c:\scripts\Config-DC1.ps1 
Zur Vorbereitung legt bitte auf einem Domaincontroller das Skript c:\scripts\Config-DC1.ps1 an

Import-Module activedirectory

$RequiredCommands = @(
"Get-Command",
"Get-FormatData",
"Out-Default",
"Select-Object",
"out-file",
"Measure-Object",
"Exit-PSSession",

"Enable-ADAccount",
"Disable-ADAccount",
"Get-ADUser"
"Format-List"
)
$ExecutionContext.SessionState.Applications.Clear()
$ExecutionContext.SessionState.Scripts.Clear()
Get-Command -CommandType Cmdlet, alias, function | ?{$RequiredCommands -notcontains $_.Name} | %{$_.Visibility="Private"}
$ExecutionContext.SessionState.LanguageMode="RestrictedLanguage"

- Nähere Erklärungen zu den Grundlagen gibt es unter diesem Link: PowerShell 2.0 remoting guide: Part 10 – Restricting available commands using custom session configuration
- Ich habe das Startupskript nur um die ActiveDirectory cmdlets erweitert, um eine praktische Anwendung zu demonstrieren können.
- Name und Pfad des StartupScripts sind natürlich beliebig


Schritt 1: Einmalige Registrierug der SessionConfiguration "Config-DC1" auf dem Domaincontroller DC1

Register-PSSessionConfiguration -Name "Config-DC1" -StartupScript C:\scripts\Config-DC1.ps1 -force

#Ausgabe

WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin

Name                      Type                 Keys
----                      ----                 ----
Config-DC1                Container            {Name=Config-DC1}

eine detailliertere Anleitung zum Registrieren und Unregistrieren habe ich in Kapitel 4.2.1 -> Beispiel 1 erstellt.


Schritt 2: Betreten einer Session mit einer Sessionconfiguration. Dies kann testweise auf dem lokalen, oder von einem RemoteRechner aus geschehen

Enter-PsSession -configurationname config-dc1 -computername dc1
[dc1]: PS>get-command *
#Ausgabe der verfügbaren cmdlets

CommandType     Name                                                Definition
-----------     ----                                                ----------
Cmdlet          Disable-ADAccount                                   Disable-ADAccount [-Ident
Cmdlet          Enable-ADAccount                                    Enable-ADAccount [-Identi
Cmdlet          Exit-PSSession                                      Exit-PSSession [-Verbose]
Cmdlet          Format-List                                         Format-List [[-Property]
Cmdlet          Get-ADUser                                          Get-ADUser -Filter <Strin
Cmdlet          Get-Command                                         Get-Command [[-ArgumentLi
Cmdlet          Get-FormatData                                      Get-FormatData [[-TypeNam
Cmdlet          Measure-Object                                      Measure-Object [[-Propert
Cmdlet          Out-Default                                         Out-Default [-InputObject
Cmdlet          Out-File                                            Out-File [-FilePath] <Str
Cmdlet          Select-Object                                       Select-Object [[-Property

Wir sehen hier genau die cmdlets wieder, die wir im Startupscript in Schritt 0 definiert haben. Ausschliesslich diese cmdlets stehen in dieser Remotesession auch zur Verfügung


Schritt 3: ADUser bearbeiten und Verlassen der Session

[dc1]: PS>get-aduser Karl_Napf | select-object userprincipalname,enabled | format-list

#Ausgabe
userprincipalname : Karl_Napf@Dom1.intern
enabled           : True

 

[dc1]: PS>disable-adaccount Karl_Napf
[dc1]: PS>get-aduser Karl_Napf | select-object userprincipalname,enabled | format-list
#Ausgabe
userprincipalname : Karl_Napf@Dom1.intern
enabled           : False

 

[dc1]: PS>enable-adaccount Karl_Napf
[dc1]: PS>exit-pssession

 

4.2.4 Sicherheitsbeschreibung einer Sitzungskonfiguration

Richtig rund und interessant werden Sessionconfigurations, wenn wir normalen Anwendern den Aufruf der Powershell mit einem nur eingeschränkten Befehlssatz erlauben können. Im Ausgangszustand der Sessionconfiguration können nur Administratoren die RemoteSession eröffen.
In diesem Kapitel werde ich zeigen, wie wir die Berechtigungen so verändern können, dass nicht mehr nur ausschliesslich Administratoren, sondern normale Domänenaccounts bestimmte Aufgaben mit der Powershell remote erledigen können.

4.2.4.1 Security Descriptor Definition Language (SDDL)

MSDN: Security Descriptor Definition Language

MSDN: SID Strings

Der Zugriff auf die SessionConfigurationen wird über Berechtigungen gesteuert, oder  präziser ausgedrückt: über die "security descriptor definition language (SDDL)" in einem Registrykey. (siehe Kapitel 4.2.2 Standardsitzungskofiguration Beispiel 2)
Es ist nicht unbedingt notwendig die SDDL zu verstehen, um Berechtigungen zu setzen, da die Powershell mit "Set-PSSessionConfiguration -ShowSecurityDescriptorUI" auch die Möglichkeit bietet, Berechtigungen über eine GUI zu setzen.
Trotzdem will ich fürs Verständnis die SDDL kurz beschreiben und zumindest die Links zum Nachschlagen aufführen. Die prinzipielle Kenntnis über die Bedeutung der Begriffe " Owner", "Primary Group", "DACL", "ACE" und "SACL" setze ich bei euch, wenn ihr euch für die SDDL interessiert, einfach mal voraus. :-)


Beispiel 1a: Analyse eines SDDL-Strings (Grundstruktur)

Am besten holen wir uns den Securitydescriptor der integrierten Sessionconfiguration "microsoft.powershell" und sehen diesen genauer an:

get-pssessionconfiguration  |  where{$_.name -eq 'microsoft.powershell'} | fl name,Securitydescriptorsddl

(vergleiche auch Kapitel 4.2.2 Beispiel 1)

In die Ausgabe unten habe ich ein paar Erklärungen farblich eingefügt:

-Die roten Kommentare zeigen die Struktur eines SDDL-Strings,  der aus den vier Hauptkomponenten owner (O:), primary group (G:), DACL (D:) und SACL (S:) besteht. Im Beispiel unten ohne SACL(S:)!
Genauer nachlesen kann man die Struktur im oberen Teil dieses Artikels MSDN: Security Descriptor String Format

- Die blauen Kommentare erklären die beiden verwendeten Strings für den Owner (NS) und die Primary Group (BA). MSDN: SID Strings

In diesem Beispiel sind die beiden ersten Komponenten "Owner" und "Primary Group" sind für die Sessionconfiguration nicht so wichtig. Mitnehmen kann man aus diesem Beispiel die etwas seltsame Schreibweise, bei der der Doppelpunkt ":" kein Trennzeichen darstellt und eine neue Komponente nicht einmal durch ein Space getrennt wird.

# Ausgabe mit Kommentaren


Beispiel 1b: Analyse eines SDDL-Strings (ACE)

Hier wirds für unsere Belange interessanter, da im hinteren Teil des SDDL-String -beginnend mit "S:P(" -die Berechtigung der Sessionconfiguration wiedergegeben wird. Am ACE-String erkennt das System, welche User eine bestimmte Sessionconfiguration benutzen dürfen und welche nicht.
Die Struktur des ACE String wird im MSDN-Artikel 1) so beschrieben: Jede einzelne ACE ist in runden Klammern eingeschlossen, die ACE-Felder sind durch Semicolons ";" getrennt und nach folgender Reihenfolge angeordnet:

ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid 

Wir benutzen dieselbe Ausgabe wie im Beispiel 1a)

 

Die Bedeutung der ACE-Felder findet man in den Tabellen dieses Artikels  MSDN: ACE Strings wieder. Das letzte Feld "account_sid" findet man im Artikel  MSDN: SID String
 

Beispiel 1c: Anzeige der Berechtigungen mit einer GUI

wie schon weiter oben erwähnt, lassen sich die Berechtigungen einer Sessionconfiguration komfortabel über die GUI auslesen und verändern

Set-PSSessionConfiguration -ShowSecurityDescriptorUI -name microsoft.powershell -force

-force unterdrückt Rückfragen

Die Ausgabe desselben Beispiels wie in 1a) und 1b) sieht in der GUI recht unspektakulär so aus:
 

 

4.2.4.2 SessionConfiguration für bestimmte User verfügbar machen

Im Kapitel 4.2.3 Einschränken der verfügbaren cmdlets haben wir auf unserem DC bereits eine Sessionconfiguration mit dem Namen config-dc1 erstellt. Diese besitzt ein lokales Startupscript unter C:\scripts\test1.ps1, welches die Anzahl der verfügbaren cmdlets auf 11 einschränkt. Noch können aber nur Administratoren diese Configuration benutzen.
In diesem Kapitel werden wir die Berechtigung auf einen einfachen Domänenuser ausweiten, so daß dieser sich remote von einem Client auf den DC mit dieser Sessionconfiguration verbinden kann.  Dort hat er nur vordefinierten cmdlets zur Verfügung und kann einen bestimmten AD-Account aktivieren und deaktivieren.
 

zusammenfassendes Beispiel zur SessionConfiguration

In diesem abschliessenden Beispiel fügen wir die vorherigen Kapitel unter 4.2 Sitzungskonfigurationen zusammen.
Wir ermöglichen einem StandardDomänenBenutzer (Karl_Napf@dom1.intern) sich mit PSRemote mit einer auf einen Domänencontroller (DC1) zu verbinden. Dabei lädt der eine Sitzungskonfiguration (Config-DC1), die ihm einen eingeschränkten Satz con cmdlets zur Verfügung stellt, mit denen er einen andereren Domänenaccount (Heinz_Hinz@dom1.intern) aktiveren und deaktivieren kann.
 

Vorbereitungsschritt 1a: Kontrolle der angelegten Sessionconfiguration

Get-PSSessionConfiguration -name config-dc1 | Format-List

#Ausgabe

Name                   : Config-DC1
Filename               : %windir%\system32\pwrshplugin.dll
SDKVersion             : 1
XmlRenderingType       : text
lang                   : de-DE
PSVersion              : 2.0
startupscript          : C:\scripts\test1.ps1
ResourceUri            : schemas.microsoft.com/powershell/Config-DC1
SupportsOptions        : true
Capability             : {Shell}
xmlns                  : schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration
Uri                    : schemas.microsoft.com/powershell/config-DC1
ExactMatch             : false
SecurityDescriptorSddl : O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;BU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
Permission             : VORDEFINIERT\Administratoren AccessAllowed, VORDEFINIERT\Benutzer AccessAllowed


Vorbereitungsschritt 1b: Kontrolle des startupscripts c:\scripts\test1.ps1

#Dieses Startupscript stellt die sieben unbedingt notwendigen cmdlets für eine Remotesession bereit
.....
$ExecutionContext.SessionState.LanguageMode="RestrictedLanguage"

Das gesamte StartupSkript und die Registrierung der Sessionconfiguration seht ihr im Kapitel 4.2.3 Einschränken der verfügbaren cmdlets


Vorbereitungsschritt 2a: Erweitertern der Berechtigungen für die Sitzungskonfiguration "Session-DC1"

Set-PSSessionConfiguration -ShowSecurityDescriptorUI -name config-dc1 -force

führt zu folgenden GUI, in der man einen SecurityPrincipal einträgt. Ich füge in diesem Beispiel der Einfachheit halber meinen Testuser "Karl_Napf" hinzu. Im richtigen Leben wird man Sicherheitsgruppen benutzen.


Vorbereitungsschritt 2b: Kontrolle der Änderung am DC

Get-PSSessionConfiguration -name config-dc1 | format-list -property *
Name                   : Config-DC1
...
SecurityDescriptorSddl : O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;BU)(A;;GXGR;;;S-1-5-21-3207648952-1170633684-1844968635-9004)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
Permission             : VORDEFINIERT\Administratoren AccessAllowed, VORDEFINIERT\Benutzer AccessAllowed, DOM1\Karl_Napf AccessAllowed

Durch den Schritt 2a wurde dem Standardbenutzer "Karl_Napf" der Zugriff erlaubt.


Vorbereitungsschritt 3: Erweitern der Rechte auf einem AD-Konto für einen PS-User

Ich erlaube dem Domänenbenutzer "Karl_Napf" das Konto "Heinz-Hinz" zu aktivieren und zu deaktivieren.
In der MMC "Active Directory Benutzer und Computer" setzt bitte folgende Einstellungen auf eurem Testuser. (Nicht vergessen im Menü "Ansicht" die "erweiterten Features" zu aktivieren!
Dies ist selbstverständlich wieder ein einfaches theoretisches Beispiel, welches in die Praxis mit Gruppen und OrganizationalUnits übertragen werden würde.


Schritt 4: Verbinden vom Client zum Domaincontroller als Standardbenutzer

Ab jetzt werden wir sehen, ob die Vorbereitungen ordnungsgemäß durchgeführt wurden.
Die Verbindung erfolgt von einem Win7-Client zu einem W2k8R2-Domänencontroller (dc1), auf dem die Sessionconfiguration "config-dc1" registriert wurde.

Enter-PsSession -configurationname config-dc1 -computername dc1
[dc1]: PS>Get-Command
#Ausgabe

CommandType     Name                                Definition
-----------     ----                                ----------
Cmdlet          Disable-ADAccount                   Disable-ADAccount [-Identi
Cmdlet          Enable-ADAccount                    Enable-ADAccount [-Identit
Cmdlet          Exit-PSSession                      Exit-PSSession [-Verbose]
Cmdlet          Format-List                         Format-List [[-Property] <
Cmdlet          Get-ADUser                          Get-ADUser -Filter <String
Cmdlet          Get-Command                         Get-Command [[-ArgumentLis
Cmdlet          Get-FormatData                      Get-FormatData [[-TypeName
Cmdlet          Measure-Object                      Measure-Object [[-Property
Cmdlet          Out-Default                         Out-Default [-InputObject
Cmdlet          Out-File                            Out-File [-FilePath] <Stri
Cmdlet          Select-Object                       Select-Object [[-Property]

Die RemoteSession wird mit "Enter-PsSession" eingerichtet und betreten. Default haben Nicht-Administratoren nicht das Recht eine Remotesession aufzurufen.
"get-command" zeigt die für Karl_Napf verfügbaren cmdlets an. Es werden auch keine Aliase akzeptiert, etwa "FL" für "Format-List".
 

Schritt 5: Anzeigen von Eigenschaften eines Users

[dc1]: PS>get-aduser heinz_hinz
#Ausgabe

[dc1]: PS>get-aduser heinz_hinz
DistinguishedName : CN=Heinz Hinz,OU=BenutzerA,OU=scripting,DC=Dom1,DC=intern
Enabled           : True
GivenName         : Heinz
Name              : Heinz Hinz
ObjectClass       : user
ObjectGUID        : b3868ce8-4f2f-4860-88d3-3b582094a6c3
SamAccountName    : Heinz_Hinz
SID               : S-1-5-21-3207648952-1170633684-1844968635-9006
Surname           : Hinz
UserPrincipalName : Heinz_Hinz@Dom1.intern

Die Defautl AD-Berechtigungen erlauben es jedem Domänenbenutzer (hier: Karl_Napf) diese Felder von jedem anderen Domänenbenutzer (hier: Heinz_Hinz) zu lesen.


Schritt 6: Deaktivieren und Aktivieren eines Domainusers

Da wir im Vorbereitungschritt 3 dem Domänenbenutzer Karl_Napf erlaubt haben, das Konto von Heinz_Hinz zu Aktivieren und zu Deaktivieren, kann KarL_Napf dies jetzt mit den beiden ADcmdlets "Disable-ADAccount" und "Ensable-ADAccount" durchführen.

[dc1]: PS>Disable-ADAccount heinz_hinz
[dc1]: PS>get-aduser heinz_hinz | format-list SamAccountname,Enabled
#Ausgabe

SamAccountname : Heinz_Hinz
enabled        : False

 

[dc1]: PS>Enable-ADAccount heinz_hinz
[dc1]: PS>get-aduser heinz_hinz | format-list SamAccountname,Enabled
#Ausgabe

SamAccountname : Heinz_Hinz
enabled        : True

 

4.3 Remotesessions mit dem cmdlet "invoke-command"

Technet: About_Remote -> Detailbeschreibung
Technet: invoke-command

Wenn man sich die Links ansieht, erkennt man schon, daß wieder ein sehr mächtiges Werkzeug mit jeder Menge Parametern auf einen zukommt. Daher gebe ich zu Beginn einen kurzen Überblick, auf welche Features ich im Folgenden mit Beispielen näher eingehen möchte.

temporäre Verbindungen
dauerhafte Verbindungen
Vor- /Nachteile

Lohnenswert ist invoke-command, wenn man auf mehreren Rechnern nacheinander einzelne Befehle oder auch ganze Skripte ausführen möchte.
Will man hingegen auf einem Rechner arbeiten oder diesen näher untersuchen, so ist eine interactive RemoteSession, wie in Kapitel 4.4 beschrieben, besser geeignet.

Auf das Remote-Ausführen von Befehlen oder Skripten als BackgroundJobs werde ich unter "Prozesse - Dienste - Jobs" näher eingehen.

4.3.1 Remoting mit temporärer Verbindung

In den Beispielen dieses Kapitels wird eine temporäre Verbindung zum Remoterechner aufgebaut, die, sobald der invoke-command Befehl abgearbeitet ist, sofort wieder beendet wird. Die Ergebnisse auf dem Remoterechner sind danach verloren

Beispiel 1: schneller Überblick über die Laufwerke C und D auf verschiedenen Rechnern mittels Scriptblock

$Drives=Invoke-Command -computername  (get-content machines.txt) -scriptblock  {get-psdrive c,d } -usessl
$Drives 

Write-Host "`n" #eine Leerzeile für die Optik

$Drives | foreach{
Write-Host $_.name  $_.free $_.used} #vergleiche "drives | get-member"
#Ausgabe

Name     Used (GB)     Free (GB) Provider  Root     CurrentLocation                 PSComputerName                          
----     ---------     --------- --------  ----     ---------------                 --------------                          
C        10,58         23,50               C:\      Users\administrator\Documents   dom2win701                              
D        ,00                               D:\                                      dom2win701                              
C        13,57         10,84               C:\      Users\Administrator\Documents   dom2dc01                                
D        1,33                              D:\                                      dom2dc01                                

C 25230536704 11363713024
D 0 2674688
C 11640881152 14570369024
D 0 1423409152

- In der Datei machine.txt sind meine beiden Testmaschinen "dom2dc01" und "dom2win701" aufgeführt.

- Sind die Voraussetzungen vorhanden, kann man optional  die Verbindungen über ein Zertifikat mit dem Positionsparameter -usessl absichern. (siehe Kapitel 3)

- Der Skriptblock {get-psdrive c,d } wird auf jeden RemoteComputer in den Cache kopiert und dort ausgeführt.

- Man wünscht sich eventuell den Scriptblock komplett in eine Variable packen zu können. Dies ist -zumindest habe ich nichts anderes herausgefunden- nur sehr bescheiden mit dem CallOperator "&" zu verwirklichen.

- Prinzipiell kann man in einem Scriptblock beliebige und beliebig viele Powershellcommands unterbringen. Praktikabler ist es, ein Skript auf dem lokalen Rechner zu erstellen und dies mit invoke-command aufzufrufen, was ich im nächsten Beispiel zeigen werde.

- Vergleiche auch Technet: Invoke-Command Beispiel 7


Beispiel 2: Überblick über die Laufwerke auf  verschiedenen Rechnern mittels lokalem Skript

#Aufrufendes Skript oder Aufruf in der interactiven Powershell

$Computers="dom2dc1","dummyRechner","dom2win701" #Rechnerliste mit einem dummy

$Headline="`nDrive   Totalsize   Totalfreespace   Percentfree   Computername"
"$Headline"
"-"*$($Headline.length)

invoke-command -computername $Computers -filepath C:\test\getfreespace.ps1 -ErrorAction SilentlyContinue

#Skript auf C:\test\getfreespace.ps1

$drives=[system.io.driveinfo]::getdrives()

$drives | foreach {
  if ($_.totalsize -gt 0){
     $Drivename=$_.name
     $Totalsize=$($_.totalsize)/1GB
     $TotalFreeSpace=$($_.totalfreespace)/1GB
     $PercentFree=$($_.totalfreespace)/$($_.totalsize)
     $computername=get-content env:computername #Hostname
    
     $width_0=3
     $width_1=9
     $width_2=8
     $width_3=13
     $width_4=8+$computername.length
         "{0,$width_0} {1,$($width_1):0.00} GB {2,$($width_2):0.00} GB {3,$($width_3):0.0%} {4,$width_4}" -f $Drivename,$totalsize,$TotalFreeSpace,$PercentFree,$computername
  }else{
     $Drivename=$_.name
     $computername=get-content env:computername
      "{0} {1,55}" -f $Drivename,$computername
  }
}

#Ausgabe

Drive   Totalsize   Totalfreespace   Percentfree   Computername
----------------------------------------------------------------
A:\                                                DOM2DC01
C:\     24,41 GB    11,30 GB         46,3%         DOM2DC01
D:\                                                DOM2DC01
A:\                                                DOM2WIN701
C:\     34,08 GB    23,42 GB         68,7%         DOM2WIN701
D:\      0,00 GB     0,00 GB          0,0%         DOM2WIN701

- Das Skript C:\test\getfreespace.ps1 wird auf jeden RemoteComputer in den Cache kopiert und dort ausgeführt. 

- Die Computerliste ist im Array $arrcomputers definiert, die ich direkt im Invoke-command Befehl übergebe. Da die Liste auch nicht erreichbare Namen enthälten könnte, setze ich die PreferenceVariable "Erroraction" auf "SilentlyContinue", um Fehlermeldungen zu unterdrücken. Im Kapitel "Variablen und Parameter" habe ich diese Variable näher beschrieben.

- vergleiche auch Technet: Invoke-Command Beispiel 1


Beispiel 3: Parametrisierung des Scriptblocks - SecurityEventlog remote abfragen

$Logname = "security"
$number= 5
$Events=invoke-command -computername dc1 -scriptblock {param($log, $num) get-eventlog -logname $log -newest $num} -ArgumentList $Logname, $number

#$Events[-1] | gm  #Damit können alle Abfragbaren Eigenschaften ermittelt werden

$$Events[-1].message  # $logs ist ein Array. Das Element $$Events[-1] ist das zuletzt geschriebene Event
$$Events[-1].timegenerated
#Ausgabe 

Ein Konto wurde abgemeldet.

Antragsteller:
    Sicherheits-ID:        S-1-5-21-3207648952-1170633684-1844968635-1106
    Kontoname:        DOM1WIN7$
    Kontodomäne:        DOM1
    Anmelde-ID:        0x35267d4

Anmeldetyp:            3

Dieses Ereignis wird generiert, wenn eine Anmeldesitzung zerstört wird. Es kann anhand des Wertes .....

Mittwoch, 19. Januar 2011 14:30:52

4.3.2 Remoting mit dauerhafter Verbindung

Im Gegensatz zu Kapitel 4.3.1, bei dem wir jeweils nur eine temporäre Verbindung mit "invoke-command -computername" zum Remote Computer aufgebaut haben, bauen wir in diesem Kapitel eine permanente Verbindung (=Session) mit dem cmdlet "new-pssession" auf.
Eine permanente Session kann zwei Vorteile bringen:

a) möchte man die Verbindung mehrfach nutzen, so braucht die notwendige Session nur einmal aufgebaut werden, was einen spürbaren Performancegewinn bringt
b) Die Variablen auf dem Remoterechner bleiben nach Abarbeiten des "invoke-command" erhalten und können abgefragt und ausserhalb der Session weiterverarbeitet werden. (siehe das folgende Beispiel 1)


Beispiel 1: Abfrage eines Dienstes auf einem Remote Rechner

remove-pssession -computername dom2win701 -EA 0

$s = new-pssession -computername dom2win701
Invoke-Command -Session $s -ScriptBlock {$dhcp = get-service dhcp}
$DHCPStatus=Invoke-Command -Session $s -Scriptblock {$dhcp}
$DHCPStatus | select status

#Ausgabe
Status
------
Running

Anmerkungen:

- Die erste Zeile "remove-pssession -computername dom2win701 -EA 0" setze ich, um vor der Ausführung alle eventuell bestehenden Sessions mit dom2win701 zu beenden. "-EA 0" entspricht der Errorvariablen "SilentlyContinue", die Fehlermeldungen unterdrückt, wenn keine Session besteht.

- mit "$s = new-pssession -computername dom2win701" wird eine neue Session etabliert und der Variablen $s zugewiesen

- würde statt "-Session $s" der Positionsparameter "-computername dom2win701" verwendet, bekäme die Variable $DHCPStatus keinen Wert zugewiesen

 

4.4. interactive Sessions

Man kann sich eine interactive remote Session auch komplett auf den lokalen Rechner holen. Dies ist vergleichbar mit Tools wie Telnet, psexec oder rcmd, die man früher benutzte. Die Powershell bietet mit ihren Möglichekeiten soviele Vorteile (siehe Kapitel 0), daß man sich langsam von diesen altgedienten Tools, sofern noch im Einsatz, verabschieden sollte.

Auch bei einer interactiven Verbindung sollte man den Unterschied zwischen einer temporären- und einer dauerhaften Verbindung kennen:
Eine einmal mit "new-psssession" aufgebaute dauerhafte Verbindung kann ich so oft betreten mit "enter-pssession" und verlassen mit "exit-pssession" wie ich möchte, die gespeicherten Variablen gehen nicht verloren.
Eine permanente Verbindungen sollte ordnungsgemäss mit "remove-pssession" beendet werden, da ein Remoterechner nur bis zu fünf dauerhafte Remoteverbindungen akzeptiert.

Bei einer temporären Verbindung (Aufbau und Beitritt nur mit "enter-pssession") sind nach dem Verlassen mit "exit-pssession" unwiederbringlich alle gespeicherten Variablen verloren. Dafür muss man sich nicht um das Beenden von Sessions mit "remove-pssession" kümmern.

4.4.1 temporäre interaktive Session

Eine temporäre, interaktive Session wird mit dem cmdlet "enter-pssession" gestartet und mit "exit-pssession" vollständig beendet.
Zwischen diesen beiden Befehlen kann man in der Session arbeiten, als säße man direkt vor an der Console des RemoteComputers.


Beispiel 1: Ablauf einer temporären, interactiven Session

Die Session wird mit enter-pssession -computername <name> gestartet. Sobald die Session remote läuft, erscheint der Name der Remoterechners, hier "dom2dc01", im Prompt

Enter-PsSession -computername dom2dc01        #lokal
[dom2dc01]: PS C:\Users\Administrator\Documents> cd hkcu:  #ab hier remote
[dom2dc01]: PS HKCU:\> dir

    Hive: HKEY_CURRENT_USER

SKC  VC Name                           Property
---  -- ----                           --------
  2   0 AppEvents                      {}
  2  37 Console                        {ColorTable00, ColorTable01, ...}
 ...                          #gekürzt
  0   1 SessionInformation             {ProgramCount}
  1   9 Volatile Environment           {LOGONSERVER, USERDNSDOMAIN, USERDOMAIN, USERNAME...}

 

Beispiel 2: Beenden einer temporären, interactiven Session

Dieses Beispiel zeigt, daß mit "get-history" die letzten verwendeten Befehle einmal in der Remotesession und einmal in der lokalen Session an. Man sieht hier, daß die Sessions wirklich getrennt verwaltet werden.

[dom2dc01]: PS HKCU:\> get-history

  Id CommandLine
  -- -----------
   1 dir
   2 .\GetFreespace.ps1
 ...                      #gekürzt
  15 get-help about_preference_variables

[dom2dc01]: PS HKCU:\> exit-pssession

PS C:\> get-history

  Id CommandLine
  -- -----------
   1 enter-pssession -computername dom2dc01
...                            #gekürzt
   8 enter-pssession -computername dom2dc01

PS C:\> enter-pssession -computername dom2dc01
[dom2dc01]: PS C:\Users\Administrator\Documents> get-history
[dom2dc01]: PS C:\Users\Administrator\Documents>



Beispiel 3: Das cmdlet "Get-History"

Das cmdlet "Get-History (Alias ghy)" speichert default die 64 letzten Befehle, zeigt aber nur die letzten 32 an. Alle 64 gespeicherten Commands bekommt man mit

Get-History 64 -count 64

Technet: get-history

4.4.2 permanente interaktive Session

Eine permanente Session wird mit folgenden cmdlets verwaltet:

  •   new-pssession - Aufbau der Session
  •   enter-pssession - Betreten der Session
  •   exit-pssession - Verlassen der Session
  •   remove-pssession - Schliessen/ Beenden der Session
  •   get-pssession - Auflisten vorhandener Sessions

 
Beispiel 1: Aufbau und Anzeige mehrerer Remotesessions

New-PsSession -computername dc1
New-PsSession -computername dc1

Get-PsSession | fl State,Computername,InstanceID,ID,Name

#Ausgabe

State        : Opened
ComputerName : dc1
InstanceId   : 29a68db8-c0c5-4ffc-a11d-639db8ec4931
Id           : 7
Name         : Session7

State        : Opened
ComputerName : dc1
InstanceId   : af76680c-7842-44d5-8937-036cbc8a5b6a
Id           : 6
Name         : Session6

 

Mit

- enter-pssession -id 7
- enter-pssession -instanceid 29a68db8-c0c5-4ffc-a11d-639db8ec4931
- enter-pssession -name Session6

kann man jetzt dieser permanenten Remotession beitreten

Beispiel 2: Betreten und Verlassen einer Remotesession

Enter-PsSession -id 6
[dc1]: PS C:\Users\KarlNapf.DOM1\Documents> $b=hostname
[dc1]: PS C:\Users\KarlNapf.DOM1\Documents> Exit-PsSession
PS C:\Powershell\MyScripts>

 

Wir betreten hier die Session mit der ID 7, weisen dort der Variable $b den Rechnernamen (=hostname) zu und verlassen die Session wieder. Betreten wir später wieder dieselbe Session, so ist dort nachwievor die Variable $b noch vorhanden.


Beispiel 3: Beenden aller Sessions zu Computer dc1

Remove-PsSession -computername dc1

4.5 implizite RemoteSessions

Implizite Remotesessions sind wieder etwas, wo man einerseits über die genialen Ideen der Powershelldesigner staunt und sich andererseits über die Einfachheit der Umsetzung freut.

Mit einer impliziten Session bekommt man die cmdlets, die ein Remoterechner zur Verfügung hat, ohne Installation auf seiner lokalen Maschine zur Verfügung gestellt und kann damit lokal arbeiten. Öffnet man zum Beispiel die Powershell V2.0 auf einer Windows7 Maschine, so hat man ohne vorherigen Import des activedirectory-Moduls (siehe ActiveDirectory -> 2 Powershell und ActiveDirectory unter W2K8R2, Win7, W2K3) keinen Zugriff auf die AD-cmdlets.
Anstelle eines Modulimports kann man eine implizite Session zu einem Domaincontroller unter Windows2008-R2, auf dem das activedirectory-Modul default installiert ist, aufbauen und damit, ohne den Windows7 Client zu verändern, die AD-cmdlets des DCs nutzen.
Mit einer implizit Session kann man sogar in einer Windows2003/ XP Session, die cmdlets des Activedirectory-Modules verfügbar machen. In dem im Kapitel 4.5.2 aufgeführten Artikel von Don Jones wird dies beschrieben.

Mit Implicit Remoting lassen sich also Erweiterungen, die auf anderen Rechnern installiert sind, importieren. Beispiele sind Erweiterungen für Sharepoint, HyperV von codeplex, dem MSDN: Windows7 Ressource Kit Powershell Pack (siehe auch: Lee Holmes: Introducing the Windows 7 Resource Kit PowerShell Pack) und andere. 

Wichtig für das Verständnis finde ich diesen beiden Punkte:
- Die Remote-cmdlets werden auf dem RemoteComputer ausgeführt, auch wenn sie wie lokale cmdlets benutzt werden können!
- Umgekehrt zum Remoting über invoke-command oder über interactive Sessions wird bei Implicit RemoteSessions der lokale Rechner mit cmdlets des RermoteRechner gesteuert.

4.5.1 Import-PSSession

Technet: Import-PSSession

Dieses Kapitel "4.5.1 Import-PSSession" und das nächste Kapitel "4.5.2 Export-PSSession" hören sich so an, als ob das eine cmdlet das Gegenteil des anderen wäre. Dem ist aber nicht so, sondern beide cmdlets führen eine unterschiedliche Umsetzung einer "Impliziten Session" durch.
Mit Import-Session werden temporär cmdlets vom RemoteComputer in die lokale Session importiert. Export-Session exportiert cmdlets des RemoteComputers zuerst in ein Module, welches im Filesystem gespeichert wird und das anschliessend über Import-Module in lokale Sessions importiert werden kann.


Beispiel 1: Import der Sharepoint-cmdlets in eine lokale Session

Das Beispiel zeigt, wie man die cmdlets aus einem SnapIn von einem Remoteserver verfügbar machen kann. Detaillierte Erklärungen zu den Befehlen folgen unter Beispiel 2.

$MySession = New-PSSession -ComputerName SharepointServer
Invoke-Command -Session $MySession -ScriptBlock {Add-PSSnapin Microsoft.SharePoint.PowerShell}
Import-PSSession -Session $MySession -Prefix MyRemote

 
Beispiel 2: Import der ActiveDirectory-cmdlets in eine lokale Session

Dieses Beispiel zeigt den Import eines Modules

$MySession=new-pssession -computername dc1
invoke-command -session $MySession -scriptblock {import-module ActiveDirectory}
Import-Pssession -Session $MySession -module ActiveDirectory -Prefix MyRemote -Commandtype All

get-command New-MyRemote*
get-help Set-MyRemoteADUser
#Ausgabe von get-command New-MyRemote*

CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        New-MyRemoteADComputer                                ...
Function        New-MyRemoteADFineGrainedPasswordPolicy               ...
Function        New-MyRemoteADGroup                                   ...
Function        New-MyRemoteADObject                                  ...
Function        New-MyRemoteeADOrganizationalUnit                      ...
Function        New-MyRemoteADServiceAccount                          ...
Function        New-MyRemoteADUser                                    ...


#Ausgabe von get-help Set-MyRemoteADUser (gekürzt)

NAME
    Set-ADUser

ÜBERSICHT
    Ändert einen Active Directory-Benutzer.

SYNTAX
    Set-ADUser [-Identity] <ADUser> [-AccountExpirationDate <System.Nullable[System.DateTime]>]
    System.Nullable[bool]>] [-Add <hashtable>] [-AllowReversiblePasswordEncryption <System.Nullable[bool]>]

1) zu einem RemoteDomaincontroller mit new-pssession eine permanente Remotesession aufgebaut. 
2) In die Session auf dem Remoterechner wird das ActiveDirectory-Module dazugeladen, welches auf einem DC standardmässig installiert ist.
3) die RemoteSession wird auf den lokalen Rechner importiert

folgende Parameter sind bei 3) bei "import-pssession" interessant

-Session $MySession: gibt die zu importierende Session an

-Module -module: beschränkt die importierten cmdlets auf diese Module. Die Angabe ist sinnvoll, da sonst der Aufbau der impliziten Session unnötig lange dauert.

-Prefix Remote: Mit diesem Parameter können Sie potenzielle Namenskonflikte aufgrund unterschiedlicher Befehle mit identischem Namen in der Sitzung vermeiden. Wenn Sie beispielsweise das Präfix "Remote" angeben und anschließend das Cmdlet "Get-Date" importieren, wird da s Cmdlet in der Sitzung als Get-RemoteDate bezeichnet, und es wird nicht mit dem ursprünglichen Cmdlet "Get-Date" verwechselt. (aus der OnlineHilfe)

-AllowClubber: Importiert die angegebenen Befehle, auch wenn sie die gleichen Namen wie Befehle in der aktuellen Sitzung aufweisen.
Wenn Sie einen Befehl mit dem gleichen Namen wie ein Befehl in der aktuellen Sitzung importieren, werden die ursprünglichen Befehle vom importierten Befehl ausgeblendet oder ersetzt. Weitere Informationen finden Sie unter "about_Command_Precedence".
Standardmäßig werden mit Import-PSSession keine Befehle importiert, die die gleichen Namen wie Befehle in der aktuellen Sitzung aufweisen.
(aus der OnlineHilfe)

In dem Beispiel bekommen alle importierten cmdlets die Ergänzung (-prefix) "MyRemote" vor das Hauptwort "New-ADGroup" wird als "New-MyRemoteADGroup" importiert.
cmdlets deren Namen bereits auf der lokalen Maschine existieren, werden nicht importiert (-Allowclubber ist nicht gesetzt)

- Alle importierten cmdlets werden auf dem RemoteRechner ausgeführt.


Beispiele 3: Import eines Modules aus dem Powershellpack des Windows7 ResourceKits

Das Powershellpack kann kostenlos von der MSDN heruntergeladen und aus dem msi-File installiert werden. Die Installation wirft allerdings einige Fehlermeldungen aus ("falscher Bezeichner"). Trotzdem funktionieren, soweit ich das beurteilen kann, die bereitgestellten Module.
 

Beispiel 3a: die cmdlets des Modules "TaskScheduler" auf einer lokalen Maschine auflisten

Bevor man ans Importieren von cmdlets geht, sollte man einmal an der Konsole der Remotemaschine überprüfen, ob der Modulimport  funktioniert und die cmdlets verfügbar sind.

Import-Module taskscheduler
Get-Command -module taskscheduler -verb *
#Ausgabe

CommandType     Name
-----------     ----
Function        Add-TaskAction
Function        Add-TaskTrigger
Function        Connect-ToTaskScheduler
Function        Get-RunningTask
Function        Get-ScheduledTask
Function        New-Task
Function        Register-ScheduledTask
Function        Remove-Task
Function        Start-Task
Function        Stop-Task

 
Beispiel 3b: Importieren der cmdlets des Modules "TaskScheduler" aus einer RemoteMaschine

$MySession = New-PSSession -ComputerName dom1win7
Invoke-Command -Session $MySession -ScriptBlock {import-module taskscheduler}
Import-Pssession -Session $MySession -module taskscheduler -Prefix MyRemote -Commandtype All

get-command *MyRemote*
#Ausgabe gekürzt

CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        Add-MyRemoteTaskAction                              ...
Function        Add-MyRemoteTaskTrigger                             ...
Function        Connect-MyRemoteToTaskScheduler                     ...
...

- Alle importierten cmdlets erhalten vor dem Verb den im Positionsparamater Prefix angegebenen Zusatz "MyRemote".
- Mit "Commandtype All" werden alle Typen von Befehlsobjekten importiert. Man kann die Befehlsobjekte auch beschränken mit "Commandtype cmdlet" oder "Commandtype Alias"

Das cmdlet Import-PSSession enthält noch einige Positionsparameter mehr, mit denen sich ganz genau die importierenden cmdlets definieren lassen. Diese Parameter sind in der onlinehilfe oder in dem am Anfang des Kapitels angegebenen Technetlink nachschlagbar.


Beispiel 3c: Arbeiten mit dem importierten cmdlet "Start-Task"

Get-Help Start-MyRemoteTask
#Ausgabe
NAME
    Start-Task

ÜBERSICHT
    Starts a scheduled task

SYNTAX
    Start-Task [<CommonParameters>]

BESCHREIBUNG
    Starts running a scheduled task.
    The input to the command is the output of Get-ScheduledTask.

Das Look-and Feel der importierten cmdlets lässt vielleicht vergessen, daß die Befehle auf dem Remoterechner abgearbeitet werden und dessen Ressourcen beanspruchen.
 

4.5.2 Export-PSSession

Don Jones im TechNet Magazine:  Implicit Remoting

Technet: Export-PSSession


Beispiel 1: Import eines Modules aus dem Powershellpack des Windows7 ResourceKits

Auch in diesem Beispiel benutze ich ein das Modul Taskscheduler aus dem Windows7 ResourceKit MSDN: Windows7 Ressource Kit Powershell Pack, welches nur auf dem Remoterechner installiert ist und dessen Befehle auf dem lokalen Rechner verfügbar gemacht werden sollen.
(vergleiche auch Beispiel 3 im Kapitel 4.5.1 Import-PSSession)


Beispiel 1a: Importieren der cmdlets des Modules "TaskScheduler" aus einer RemoteMaschine

$MySession = New-PSSession -computerName dom1win7
invoke-command -session $MySession -Scriptblock {import-module taskscheduler}
Import-Pssession -Session $MySession -module taskscheduler -Prefix MyRemote -Commandtype All
#Ausgabe

ModuleType Name                      ExportedCommands
---------- ----                      ----------------
Script     tmp_551bf780-ec1e-4ad7... {Remove-Task, Get-ScheduledTask, Stop-Task, Add-TaskTrigger...}

 

Anzeige der importierten cmdlets

get-command -module taskscheduler -verb *
#oder
get-command *myremote*
#Ausgabe

CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        Add-MyRemoteTaskAction                              ...
Function        Add-MyRemoteTaskTrigger                             ...
Function        Connect-MyRemoteToTaskScheduler                     ...
Function        Get-MyRemoteRunningTask                             ...
Function        Get-MyRemoteScheduledTask                           ...
Function        New-MyRemoteTask                                    ...
Function        Register-MyRemoteScheduledTask                      ...
Function        Remove-MyRemoteTask                                 ...
Function        Start-MyRemoteTask                                  ...
Function        Stop-MyRemoteTask                                   ...

 

Beispiel 1b) Exportieren der Taskscheduler-cmdlets in ein Module

Export-PSSession -session $session -commandname *-Task* -outputmodule RemTask -allowclobber
#Ausgabe

    Verzeichnis: C:\Users\blub.DOM1\Documents\WindowsPowerShell\Modules\RemTask


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        09.02.2011     15:46      20636 RemTask.psm1
-a---        09.02.2011     15:46         99 RemTask.format.ps1xml
-a---        09.02.2011     15:46        587 RemTask.psd1

Unter dem Pfad "C:\Users\blub.DOM1\Documents\WindowsPowerShell\Modules\RemTask" wird das neu erstellte Module gespeichert

09.02.2011  15:46                99 RemTask.format.ps1xml
09.02.2011  15:46               587 RemTask.psd1
09.02.2011  15:46            20.636 RemTask.psm1
               3 Datei(en),         21.322 Bytes

 

Beispiel 1c) Importieren der Taskscheduler-cmdlets in eine lokale PowershellSession

Remove-PSSession -session $session #genauso kann man eine neue PS-Sitzung starten
Import-Module RemTask -prefix myTask
Get-Command *myTask* #Anzeige der importierten Sessions
#Ausgabe

PS C:\Users\blub.DOM1> get-command *mytask*

CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        Add-myTaskTaskAction                                ...
Function        Add-myTaskTaskTrigger                               ...
Function        New-myTaskTask                                      ...
Function        Remove-myTaskTask                                   ...
Function        Start-myTaskTask                                    ...
Function        Stop-myTaskTask                                     ...



Beispiel 2: Erneutes Laden eines Moduls
In einer neuen Powershellsession auf dem Rechner, auf dem im letzten Beispiel unter "C:\Users\blub.DOM1\Documents\WindowsPowerShell\Modules\RemTask" das Modul RemTask abgelegt wurde, kann man sich das Modul ganz leicht erneut importieren

Import-Module RemTask -prefix myTask
Get-Command *mytask*
#Ausgabe

CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        Add-myTaskTaskAction                                ...
Function        Add-myTaskTaskTrigger                               ...
Function        New-myTaskTask                     

Das in Beispiel 1 erstellte Module "RemTask" enthält keine Kopien von cmdlets aus dem Module Taskscheduler am Remoterechner, sondern nur eine Art Links auf diese cmdlets
(siehe den Artikel von Don Jones)

The cmdlets aren’t actually copied to your local computer. Instead, the locally created module serves as a kind of shortcut. The cmdlets will always be executed on the remote domain controller, but the cmdlets will seem to be running locally.