Zum Inhaltsverzeichnis Das Filesystem

---------------------------------------------------------------------------------------

 

1 Pfade

Der erste Block eines Skriptes, das sich mit Objekten im Filesystem beschäftigt, dürfte wohl meistens der Weg zum gewünschten Verzeichnis sein, in dem irgendetwas unternommen werden soll. Entweder bewegt man das aktuelle Arbeitsverzeichnis der Powershellsession gleich komplett zum Ziel, sowie man das aus der commandshell (cmd.exe "cd /d c:\temp") gewöhnt ist, oder gibt seinen Powershellbefehlen den richtigen Pfad jedesmal mit.

Liegt der Zielpfad bereits vor, so ist das Navigieren zu dem Pfad natürlich einfach. Muss man den Zielpfad erst neu konstruieren, so helfen eine Reihe von cmdlets weiter. Im nächsten Unterkapitel 1.1 spezielle Pfade untersuche ich, wo besondere, vom Betriebssystem oder von der Powershell selbst vorgegebene, Pfade liegen und wie sie ausgelesen werden können.

Im Kaptilel 1.2 Powershellcmdlets zur Pfadbearbeitung werden die cmdlets untersucht, die man benötigt, wenn ein solcher Pfad noch nicht, oder nur teilweise bekannt ist.

 

1.1 spezielle Pfade

Zwei Tipps zu Beginn:

- Wenn im Skript das aktuelle Arbeitsverzeichnis verändert wird, so merkt euch vor der Änderung dieses Verzeichnis und setzt das Arbeitsverzeichnis am Ende des Skripts wieder auf die Ausgangsposition - siehe Beispiel 1c unter 1.1.2 das aktuelle Arbeitsverzeichnis
Für den Skriptbenutzer ist das einfach angenehmer.

- Arbeitet möglichst mit den in Windows, .Net oder in der Powershell vordefinierten Pfaden. Dadurch erreicht ihr, daß euer Skript  kompatibler über verschiedene Betriebssystemversionen, Architekturversionen(32/ 64 bit) und Sprachversionen ist, als mit selbst zusammengesetzten Pfaden, die vielleicht nur auf eurem Entwicklerrechner existieren.

 

1.1.1 wo sind "spezielle Pfade" hinterlegt

Ich zeige hier drei Möglichkeiten, die ein Powershellprogrammierer nutzen kann, um spezielle Dateien und Verzeichnisse zu ermitteln.

- automatic Variables
- Umgebungsvariablen
- Eigenschaften von .Net Klassen (Registry)

 

1.1.1.1 automatic Variables

Technet:  about_Automatic_Variables

Neben vielen anderen Variablen enthalten die "automatic variables" Liste 6 Variablen, die recht häufig vorkommende Pfade beinhalten.


Beispiel 1a: Liste der Pfadvariablen unter den "automatic variables"

Lest euch die Beschreibungen einfach mal durch. Einige Variablen davon sind euch bestimmt schon begegnet. Beispielwerte von einem Windows7 System findet ihr im nach folgenden Beispiel 1b.

get-help about_automatic_variables

#Ausgabe gekürzt

    $Home
       Enthält den vollständigen Pfad zum Stammverzeichnis des
       Benutzers. Diese Variable ist die Entsprechung der
       %homedrive%%homepath%-Umgebungsvariablen, normalerweise
       "C:\Dokumente und Einstellungen\<Benutzer>".

    ....


    $MyInvocation
       Enthält ein Objekt mit Informationen zum aktuellen Befehl,
       z. B. ein Skript, eine Funktion oder einen Skriptblock.
       Mithilfe der Informationen im Objekt, z. B. mit dem Pfad und dem
       Dateinamen des Skripts ($myinvocation.mycommand.path) oder mit dem
       Namen einer Funktion ($myinvocation.mycommand.name), können Sie den
       aktuellen Befehl bestimmen. Dies ist besonders hilfreich beim Suchen
       des Namens des derzeit ausgeführten Skripts.

    ....

    $Profile
       Enthält den vollständigen Pfad des Windows PowerShell-Profils
       für den aktuellen Benutzer sowie der aktuellen Hostanwendung.
       Mithilfe dieser Variablen können Sie das Profil in Befehlen
       darstellen. Mit der Variablen können Sie beispielsweise in
       einem Befehl bestimmen, ob ein Profil erstellt wurde:

           test-path $profile

       Mit der Variablen können Sie in einem Befehl auch ein Profil
       erstellen:

           new-item -type file -path $pshome -force

       Darüber hinaus können Sie sie in einem Befehl verwenden, um
       das Profil in Editor zu öffnen:

           notepad $profile

    ....

    $PsHome
       Enthält dem vollständigen Pfad des Installationsverzeichnisses für
       Windows PowerShell, normalerweise "%windir%\System32\WindowsPowerShell
       \v1.0". Sie können diese Variable in den Pfaden für Windows
       PowerShell-Dateien angeben. Mit dem folgenden Befehl werden z. B. die
       konzeptuellen Hilfethemen nach dem Wort "Variable" durchsucht:

            select-string -pattern variable -path $pshome\*.txt

    ....  

    $PSScriptRoot
       Enthält das Verzeichnis, aus dem das Skriptmodul ausgeführt wird.
       Diese Variable ermöglicht Skripts den Zugriff auf andere
       Ressourcen über den Modulpfad.

    ....

    $Pwd
       Enthält ein Pfadobjekt, das den vollständigen Pfad des
       aktuellen Verzeichnisses darstellt.

    ....

SEE ALSO
    about_Hash_Tables
    about_Preference_Variables
    about_Variables

 

Beispiel 1b: Werte der Pfadvariablen

"`$Home: {0}" -f $home
"`Skriptpfad: {0} -f $($MyInvocation.InvocationName)
"`$Profile: {0}" -f $Profile
"`$PsHome: {0}" -f $PsHome
"`$PSScriptRoot: {0}" -f $PSScriptRoot
"`$Pwd: {0}" -f $Pwd

#Ausgabe

$Home: C:\Users\karl_napf
Skriptpfad: C:\Powershell\MyScripts\test.ps1
$Profile: C:\Users\karl_napf\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
$PsHome: C:\Windows\System32\WindowsPowerShell\v1.0
$PSScriptRoot:
$Pwd: C:\Powershell\MyScripts

Im Gegensatz zu den anderen 4 Variablen, sind die Variablen $pwd und $MyInvocation keine Strings der Klasse [system.string], sondern $pwd ist ein Objekt der Klasse [System.Management.Automation.PathInfo] und $MyInvocation ist ein Object der Klasse [System.Management.Automation.InvocationInfo]. Auf $MyInvocation gehe ich im Unterkapitel 1.1.2 "das aktuelle Arbeitsverzeichnis" im Beispiel 2 näher ein.


Im nächsten Beispiel benutze ich die Variable $pwd

Beispiel 2: Provider des aktuellen Pfades bestimmen

Set-Location HKLM:\SYSTEM\CurrentControlSet
$PWD
$PWD.Provider.Name

"`nProviderwechsel`n"

Set-Location $env:windir
$PWD
$PWD.Provider.NamePath                                                                                                                                                                     

#Ausgabe

----                                                                                                                                                                      
HKLM:SYSTEM\CurrentControlSet                                                                                                                                
Registry

Providerwechsel

C:\Windows                                                                                                                                     
FileSystem

Durch die Provider wird das Navigieren im Filesystem, in der Registry oder im Zertifikatsstore einheitlich und transparent. 

Technet:  Windows PowerShell – Provider-Hilfethemen

 

1.1.1.2 Umgebungsvariablen - Environment Variables

Technet:  about_Environment_Variables

Umgebungsvariablen stellen eine Reihe von Informationen des Betriebssystems und des Userprofiles direkt als Variable zur Verfügung. Darunter sind -deswegen behandle ich das Thema hier- auch etliche Pfade.


Beispiel 1: Anzeige der Umgebungsvariablen

set-location env:
get-childitem

#[system.environment]::getenvironmentvariables()

#Ausgabe

Name                           Value                                                   
----                           -----                                                   
ALLUSERSPROFILE                C:\ProgramData                                          
APPDATA                        C:\Users\karl_napf\AppData\Roaming                      
CLIENTNAME                     V100WPWMK1II328                                         
CommonProgramFiles             C:\Program Files\Common Files                           
CommonProgramFiles(x86)        C:\Program Files (x86)\Common Files                     
CommonProgramW6432             C:\Program Files\Common Files                           
COMPUTERNAME                   DOM1CLI01                                               
ComSpec                        C:\Windows\system32\cmd.exe                             
DEFLOGDIR                      C:\ProgramData\McAfee\DesktopProtection                 
FP_NO_HOST_CHECK               NO                                                      
HOMEDRIVE                      C:                                                      
HOMEPATH                       \Users\karl_napf                                        
LOCALAPPDATA                   C:\Users\karl_napf\AppData\Local                        
LOGONSERVER                    \\DOM1DC01                                              
NUMBER_OF_PROCESSORS           1                                                       
OS                             Windows_NT                                              
Path                           C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbe...
PATHEXT                        .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC   
PROCESSOR_ARCHITECTURE         AMD64                                                   
PROCESSOR_IDENTIFIER           Intel64 Family 6 Model 23 Stepping 6, GenuineIntel      
PROCESSOR_LEVEL                6                                                       
PROCESSOR_REVISION             1706                                                    
ProgramData                    C:\ProgramData                                          
ProgramFiles                   C:\Program Files                                        
ProgramFiles(x86)              C:\Program Files (x86)                                  
ProgramW6432                   C:\Program Files                                        
PSModulePath                   C:\Users\karl_napf\Documents\WindowsPowerShell\Modules...
PUBLIC                         C:\Users\Public                                         
SESSIONNAME                    RDP-Tcp#0                                               
SystemDrive                    C:                                                      
SystemRoot                     C:\Windows                                              
TEMP                           C:\Users\KARL_N~1\AppData\Local\Temp                    
TMP                            C:\Users\KARL_N~1\AppData\Local\Temp                    
USERDNSDOMAIN                  DOM1.INTERN                                             
USERDOMAIN                     DOM1                                                    
USERNAME                       Karl_napf                                               
USERPROFILE                    C:\Users\karl_napf                                      
VS90COMNTOOLS                  c:\Program Files (x86)\Microsoft Visual Studio 9.0\Com...
VSEDEFLOGDIR                   C:\ProgramData\McAfee\DesktopProtection                 
windir                         C:\Windows                                              
windows_tracing_flags          3                                                       
windows_tracing_logfile        C:\BVTBin\Tests\installpackage\csilogfile.log   

Anmerkung 1 : Weitere interessante Informationen zum Betriebssystem liefert die WMI-Klasse Win32_Computersystem, wenn auch dort keine Pfade enthalten sind. 

Anmerkung 2: Mit jeder Windowsversion kommen neue Umgebungsvariablen dazu. Dies ist eine Liste von einem Win7-Domänenclient. Unter XP sind es einige Variablen weniger

Anmerkung 3 : Manchen Umgebungsvariablen merkt man gelegentlich ihre Vergangenheit an. So sind der TEMP- und TMP Pfad oder Teile davon auf 8 Stellen gekürzt.

Falls diese Verkürzung stört, muss man auf .Net ausweichen
 MSDN - System.IO Path-Klasse

$outputPath =[io.path]::GetTempPath()
$outputPath

#Ausgabe
C:\Users\karl_napf\AppData\Local\Temp\



Beispiel 2: Setzen/ Ändern von Umgebungsvariablen

 Technet: Creating and Modifying Environment Variables

In Beispiel 1 haben wir alle Umgebungsvariablen des Systems angezeigt. Genaugenommen haben wir aber die Variablen aus einem userspezifischen Store und einem maschinenspezifischen Store ausgelesen. Beide Stores befinden sich in lesbarer und beschreibbarer Form in der Registry unter

HKEY_CURRENT_USER\Environment  (Userspezifisch)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment  (Maschinenspezifisch)

Einige zusätzliche Variablen wie "Userprofile" werden dynamisch erzeugt. Alle Variablen zusammen sind  "prozessspezifisch." Die Umgebungsvariablen, die nicht in der Registry stehen, sind beim nächsten Start der Powershell dann auch wieder verschwunden.

In maschinenspezifische Umgebungsvariablen kann man beispielsweise Werte während der Installation hineinsetzen, wie Standort, Inventarnummer oder auch Werte, die später bei Softwareninstallationsverfahren benötigt werden. Wenn man aus den Umgebungsvariablen den Serverfunktionstyp (Domaincontroller, Exchangeserver), oder ob der Server physikalisch oder virtuell existiert und vieles mehr, dann erleichtert dies die spätere Administration der Maschine deutlich.

#Setzen einer userspezifischen Umgebungsvariable (dauerhaft)

$name="uservariable_1"
$wert="uservalue_1"
$context="user"
[Environment]::SetEnvironmentVariable($name, $wert, $context)


#Setzen einer maschnenpezifischen Umgebungsvariable (dauerhaft)

$name="machinevariable_1"
$wert="machine_value_1"
$context="machine"
[Environment]::SetEnvironmentVariable($name, $wert, $context)


#Setzen einer prozesspezifischen Umgebungsvariable (flüchtig)

$name="processvariable_1"
$wert="process_value_1"
$context="process"
[Environment]::SetEnvironmentVariable($name, $wert, $context)
#$env:$name = $wert #alternativ

 

Beispiel 3: Auslesen von Umgebungsvariablen

$a=[system.environment]::GetEnvironmentVariable("windir")
#$a=$env:windir  #identisch
$a

#Ausgabe

C:\Windows

Da "windir" bereits zum Prozessstart als Maschinenvariable vorhanden war, ist sie automatisch auch eine Prozessvariable. Dadurch kann sie einfach ohne Angabe des Kontextes ausgelesen werden.

Um die im vorigen Beispiel neu erzeugten User- und Machinenvariablen auszulesen, muß entweder Powershell neu gestartet werden, oder der Kontext mit angegeben werden.

$name="machinevariable_1"
$context="machine"
[Environment]::GetEnvironmentVariable($name, $context)

#Ausgabe
machine_value_1

Anmerkung: Variablen mit Prozesskontext sind sofort verfügbar, aber leider nicht Powershellsession übergreifend, sondern nur in der aktuellen Session. Man kann also nicht zwei parallele Powershellsessions geöffnet haben und Umgebungsvariablen austauschen.

 

1.1.1.3 GetFolderpath - Specialfolder

Neben den gezeigten Umgebungsvariablen und den "automatic variables" gibt es noch die SpecialFolder, die in der Registry unter HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders aufgelistet sind. Diese Pfade können auch über Group Policies aus dem ActiveDirectory manipuliert werden. siehe Technet:  Folder Redirection Overview 


Beispiel 1: Anzeige der Specialfolder mit Pfad

aus MSDN:  Special Folders sample using PowerShell von Thomas Lee

# Author: Thomas Lee
 Special Folders sample using PowerShell

# Get the list of special folders
$folders = [system.Enum]::GetValues([System.Environment+SpecialFolder])

# Display these folders
"Folder Name            Path"
"-----------            -----------------------------------------------"
foreach ($folder in $folders) {
"{0,-22} {1,-15}"  -f $folder,[System.Environment]::GetFolderPath($folder)
}

#Ausgabe

Folder Name            Path
-----------            -----------------------------------------------
Desktop                C:\Users\karl_napf\Desktop
Programs               C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
Personal               C:\Users\karl_napf\Documents
Personal               C:\Users\karl_napf\Documents
Favorites              C:\Users\karl_napf\Favorites
Startup                C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Recent                 C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\Recent
SendTo                 C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\SendTo
StartMenu              C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\Start Menu
MyMusic                C:\Users\karl_napf\Music
DesktopDirectory       C:\Users\karl_napf\Desktop
MyComputer                           
Templates              C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\Templates
ApplicationData        C:\Users\karl_napf\AppData\Roaming
LocalApplicationData   C:\Users\karl_napf\AppData\Local
InternetCache          C:\Users\karl_napf\AppData\Local\Microsoft\Windows\Temporary Internet Files
Cookies                C:\Users\karl_napf\AppData\Roaming\Microsoft\Windows\Cookies
History                C:\Users\karl_napf\AppData\Local\Microsoft\Windows\History
CommonApplicationData  C:\ProgramData
System                 C:\Windows\system32
ProgramFiles           C:\Program Files
MyPictures             C:\Users\karl_napf\Pictures
CommonProgramFiles     C:\Program Files\Common Files

 

Beispiel 2: Zuweisen eines Specialfolder-Pfades zu einer Variablen

$a=[Environment]::GetFolderPath("InternetCache")
$a

#Ausgabe

C:\Users\karl_napf\AppData\Local\Microsoft\Windows\Temporary Internet Files

Diese Information könnte man dazu benutzen, regelmäßig den Cache des InternetExplorers zu bereinigen, der seine Dateien hier ablegt.

 

1.1.2 das aktuelle Arbeitsverzeichnis und das eigene Skript

 Beispiel 1a: Ändern und Abfragen des aktuellen Powershellverzeichnisses

"lokales Navigieren:"
set-location "c:\temp"
get-location #identisch mit $pwd (siehe automatic variables)

"Remote Navigieren:"
set-location "\\192.168.178.254\c$\temp"
set-location "\\dom1dc01\c$\temp"
get-location

#Ausgabe

lokales Navigieren:
Path                                                                                                                                  
----                                                                                                                                  
C:\temp                                                                                                                               

Remote Navigieren:
Microsoft.PowerShell.Core\FileSystem::\\dom1dc01\c$\temp                                                                              

 

Anzeige der Aliase von get-location und set-location

siehe: My Powershell -> Aliase -> Überblick ->Beispiel 3

"Aliase von get-location"
get-alias -definition get-location
"`nAliase von set-location"
get-alias -definition set-location

#Ausgabe

CommandType     Name                                 Definition                         
-----------     ----                                 ----------                         
Alias           gl                                   Get-Location                       
Alias           pwd                                  Get-Location                       

Aliase von set-location
Alias           cd                                   Set-Location                       
Alias           chdir                                Set-Location                       
Alias           sl                                   Set-Location                    

 

Beispiel 1b: Ändern und Abfragen des aktuellen .Net Verzeichnisses

#Setzen der Arbeitsverzeichnisse
set-location "c:\temp"
[IO.Directory]::SetCurrentDirectory("c:\")

#Abfrage mit der directoryinfo-Klasse
$a=new-object system.io.directoryinfo(".")
"{0} -- {1}" -f 'system.io.directoryinfo(".")', $a.fullname

#identisch zu
$b=[system.io.directoryinfo]"."
"{0} -- {1}" -f '[system.io.directoryinfo]"."', $b.fullname

#Abfrage mit der Directory-Klasse
$c=[System.IO.Directory]::GetCurrentDirectory()
"{0} -- {1}" -f '[System.IO.Directory]::GetCurrentDirectory()', $c

#Abfrage mit PS-cmdlet
$d=get-location
"{0} -- {1}" -f 'get-location', $d

#Ausgabe

system.io.directoryinfo(".") -- c:\
[system.io.directoryinfo]"." -- c:\
[System.IO.Directory]::GetCurrentDirectory() -- c:\
get-location -- C:\temp

Man erkennt, daß die Powershell und die Klassen unter System.IO unterschiedliche Arbeitsverzeichnisse haben.

Beispiel 1c: Ändern des Arbeitsverzeichnisses und Zurücksetzen

Zu Batchzeiten erledigten diese Aufgabe die zwei Befehle pushd und popd. In der Powershell stehen beide als Aliase der cmdlets push-location und pop-location zur Verfügung. Man kann mit push-location mehrere Pfade nacheinander auf einen Standard oder einen selbstdefinierten Stack legen und mittels pop-location in umgekehrter Reihenfolge wieder aufnehmen.

Ich persönlich finde die Speicherung von Pfaden in Variablen mit aussagekräftigen Namen übersichtlicher. Aber es mag sein, daß für bestimmte Aufgaben die Flexibilität der Stacks mehr für popd/ pushd spricht. 

Das Beispiel zeigt einmal den Weg über eine Variable und einmal den Weg über den Stack mittels der cmdlets push-location und pop-location. Das Ergebnis ist identisch.

"Arbeitsverzeichnis in einer Variable speichern `n"
$Ursprungspfad=get-location
"Ursprungspfad: $Ursprungspfad"

set-location c:\

"geänderter Pfad:  $(get-location)"
set-location $Ursprungspfad

"zurückgeänderter Ursprungspfad $(get-location)"


"`n`nArbeitsverzeichnis im Stack speichern `n"

"Ursprungspfad=$(get-location)"
pushd   #Alias von push-location

set-location c:\

"geänderter Pfad:  $(get-location)"
popd   #Alias von pop-location

"zurückgeänderter Ursprungspfad $(get-location)"

#Ausgabe

Arbeitsverzeichnis in einer Variable speichern

Ursprungspfad: C:\temp
geänderter Pfad:  C:\
zurückgeänderter Ursprungspfad C:\temp


Arbeitsverzeichnis im Stack speichern

Ursprungspfad=C:\temp
geänderter Pfad:  C:\
zurückgeänderter Ursprungspfad C:\temp

Technet:  Pop-Location

Technet:  Push-Location


Beispiel 2: Ermitteln des eigenen Skriptnamens mit Pfad
Mit der "automatic variable" $MyInvocation, die ein Objekt der MyInvocation-Klasse darstellt, kommt man über die Eigenschaft InvocationName an den vollqualifizierten Namen des aufrufenden Skripts und möglicherweise weitere interessante Informationen, siehe MSDN:  InvocationInfo Properties

$MyInvocation | select *
"Pfad dieses Skripts: $($MyInvocation.InvocationName)"

#Ausgabe

MyCommand        : test.ps1
BoundParameters  : {}
UnboundArguments : {}
ScriptLineNumber : 0
OffsetInLine     : 0
HistoryId        : 30
ScriptName       :
Line             :
PositionMessage  :
InvocationName   : C:\Powershell\MyScripts\test.ps1
PipelineLength   : 2
PipelinePosition : 1
ExpectingInput   : False
CommandOrigin    : Runspace

Pfad dieses Skripts: C:\Powershell\MyScripts\test.ps1

Anmerkung 1: Ein leerer Skriptname kommt zurück, wenn das Skript noch nicht gespeichert wurde.

Anmrekung 2: In Beispiel 2 im nächsten Kapitel 1.2 benutze ich $ myinvocation.mycommand.name um mit dem Skriptnamen zu arbeiten.

 

1.2 Powershellcmdlets zur Pfadbearbeitung

Steht der gewünschte Pfad in keiner Systemvariablen bereit, so gibt eine Handvoll cmdlets, die dann auf ihren Einsatz warten.

Beispiel 1: Anzeige der cmdlets zur Pfadbearbeitung

get-help *path*

#Ausgabe

Name                              Category  Synopsis
----                              --------  --------
Join-Path                         Cmdlet    Kombiniert einen Pfad und einen untergeordneten Pfad zu einem Pfad. Der ...
Convert-Path                      Cmdlet    Konvertiert einen Pfad aus einem Windows PowerShell-Pfad in einen Window...
Split-Path                        Cmdlet    Gibt den angegebenen Teil eines Pfads zurück.
Test-Path                         Cmdlet    Bestimmt, ob alle Elemente eines Pfads vorhanden sind.
Resolve-Path                      Cmdlet    Löst die Platzhalterzeichen in einem Pfad auf und zeigt den Inhalt des P...
about_Path_Syntax                 HelpFile  Beschreibt die Formate für vollständige und relative Pfadnamen in

Die meist verwendeten cmdlets sind zumindest bei mir "Split-Path". "Join-Path" und "Test-Path".


Beispiel 2: zentrales Logverzeichnis oberhalb des temp-Verzeichnisses erstellen, in dem jedes Skript ein spezifisches Logfile ablegt

Mit der Funktion "CentralLog" wird an zentraler Stelle -sofern noch nicht vorhanden- ein LogContainer erstellt. Dort erstellt ein PS-Skript, das diese Funktion aufruft, eine Logdatei aus dem Namen des aufrufenden Skriptes, sofern die Logdatei noch nicht existiert.
In diese Logdatei wird das Datum des Skriptaufrufs, sowie eine Message geschrieben und angehängt. Damit kann man sich bei Bedarf einen leichten Überblick verschaffen, wann welche Skripte ausgeführt wurden.

Es gibt anderere Szenarien, in denen es sinnvoller ist, eine bereits vorhandene Logdatei zu überschreiben, oder für jeden Skriptaufruf eine individuelle neue Logdatei zu erstellen, deren Name sich beispielsweise aus dem Scriptnamen und dem aktuellen Datum mit Uhrzeit zusammensetzt.

Hier gehts mir aber um ein sinnvolles Beispiel für den Einsatz einiger "path-cmdlets", wie split-path, join-path und test-path

Function CentralLog{
    param($funLogname,$funMessage)
    $LogContainer="PSLogs"   

    #Schritt 1
    $funTempPath =[io.path]::GetTempPath()
    $funParentTempPath=split-path $funTempPath -parent
    $funPSLogPath=join-path -path $funParentTempPath -ChildPath $LogContainer
    
    #Schritt 2
    $a=Test-Path -path $funPSLogPath
    if ($a -eq $false){
        New-Item -path $funPSLogPath -type directory
        "Das Verzeichnis $funPSLogPath wurde angelegt"
        }else{
        "Verzeichnis $funPSLogPath existiert schon"
        }

    #Schritt 3  
    $funoutpath=$funPSLogpath+"\"+$funLogname
    $funDateTime=get-date -f "dd-MM-yyyy HH:mm:ss"
    out-file -filepath $funOutPath -inputobject ($funDatetime+": "+$funMessage) -append
}

#Schritt 0
$skriptname=$myinvocation.mycommand.name
$Logname = ($skriptname -split "\.")[0]
$Logname=$Logname+".log"
$Message="Skript erfolgreich aufgerufen"
CentralLog $logname $Message

Erklärung:

Schritt 0:
$skriptname=$myinvocation.mycommand.name
$myinvocation ist eine der "automatic variables", die ich in Kapitel 1.1.1.1 behandelt habe. Läge der Aufruf innerhalb der function und nicht im Skript selbst, so würde der Funktionsname zurückgeliefert

$Logname = ($skriptname -split "\.")[0]
Abtrennen der Dateierweiterung .ps1 vom übrigen Skriptnamen

CentralLog $logname $Message
Funktionsaufruf: die Parameter sind durch Leerzeichen getrennt

Schritt 1:
$funTempPath =[io.path]::GetTempPath()
Einer der festgelegten Pfade die ich im Kapitel 1.1.1.2 Umgebungsvariablen vorgestellt habe. Beispielsweise unter WinXP: "C:\Dokumente und Einstellungen\KarlNapf\Lokale Einstellungen\Temp"

$funParentTempPath=split-path $funTempPath -parent
$funPSLogPath=join-path -path $funParentTempPath -ChildPath $LogContainer

Schritt 2:
Prüfen ob das Zielverzeichnis vorhanden ist. Falls nicht, wird es angelegt

Schritt 3:
Datum und Message in die Textdatei schreiben

Anmerkung: Natürlich kann man sich diese Funktion in jedes seiner Skripte hineinkopieren und dann verwenden. Powershell bietet aber auch die Möglichkeit, diese Funktion in einer einzigen Skriptdatei (Bibliothek) zentral abzulegen und diese als Include-File zu importieren. Das kann die Wartung dieser Funktion deutlich vereinfachen.
My Powershell -> 3.3.4 Include File (Dot Sourcing)

 

1.3 Pfade mit Sonderzeichen

Die Navigation im Filesystem erfolgt über den Fileprovider meist ohne große Anstrengungen. Ein bischen knifflig kann es bei der Verwendung von Sonderzeichen im Ordner- oder Dateinamen werden. Entweder hat man Glück und die Powershellentwickler haben das notwendige cmdlet mit dem Parameter " "-literalpath" ausgestattet, der alle Zeichen und Sonderzeichen so nimmt wie sie sind. Falls das cmdlet diesen Parameter nicht bereitstellt, muß man entweder den Weg über eine .Net Klasse gehen oder mit dem cmdlet new-PSDrive ein neues PSDrive anlegen. Die folgenden Beispiele zeigen die Wege


Beispiel 1: Navigieren zu einem Pfad mit dem Parameter "-Literalpath"

Das cmdlet set-location besitzt den Positionsparameter -literalpath. So ist man in der angenehmen Situation einfach diesen Parameter benutzen zu können und Sonderzeichen wie "[]" werden ohne Schwierigkeiten akzeptiert.

#set-location c:\temp\test[1] #würde einen Fehler produzieren
set-location -literalpath c:\temp\test[1]

get-location

#Ausgabe

c:\temp\test[1]

Der Wert des LiteralPath-Parameters wird genau so verwendet, wie er eingegeben wurde. Es werden keine Zeichen als Platzhalter interpretiert. Wenn der Pfad Escapezeichen enthält, müssen Sie ihn in einfache Anführungszeichen einschließen. Einfache Anführungszeichen veranlassen Windows PowerShell, Zeichen nicht als Escapesequenzen zu interpretieren. (aus der Onlinehilfe zu Set-Location)

 
Beispiel 2a: Workaround mit .Net für das cmdlet "get-acl", das kein -Literalpath enthält

#get-acl c:\temp\test[1] | select * # liefert nichts zurück
([io.directoryinfo]"C:\Temp\Test[1]").getaccesscontrol() | select *  # liefert die Accesslisten

#Ausgabe gekürzt

AccessToString          : VORDEFINIERT\Administratoren Allow  FullControl
                          VORDEFINIERT\Administratoren Allow  268435456
                         ....


Beispiel 2b: Workaround mit dem cmdlet New-PSdrive für das cmdlet "get-acl", das kein -Literalpath enthält

remove-psdrive -name myTest -EA 0 #Falls myTest schon vorhanden ist, gibt es sonst eine Fehlermeldung
new-psdrive -name myTest -psprovider filesystem -root "c:\temp\test[1]"

(get-acl myTest:).access

#Ausgabe gekürzt

AccessToString          : VORDEFINIERT\Administratoren Allow  FullControl
                          VORDEFINIERT\Administratoren Allow  268435456
                         ....

Für das cmdlet get-acl steht kein Parameter "-LiteralPath" zur Verfügung. Daher muß man entweder den kleinen Umweg über eine geeignete .Net Klasse gehen (Fündig wird man für Fileoperationen meist in den Klassen des System.IO - Namespaces. siehe MSDN:  System.IO Namespace) oder man erstellt sich mit dem cmdlet new-psdrive ein PS-Laufwerk, auf das man das cmdlet get-acl anwendet. 

Mit deutschen Sonderzeichen wie "äöüß" kommt Powershell übrigens ohne zu Zucken und ohne -literalpath zurecht.