Auf dieser Seite habe ich ein paar Anmerkungen zur Erstellung von powershell-Skripten gesammelt. Die Sammlung wird laufend erweitert.
Vorbemerkung: Wichtig hierbei ist, dass sich die Code-Schnippsel auf die aktuelle Version von Powershell beziehen. Mit jeder Version von Windows kommt eine neue Version von Powershell mit, deren Funktionsumfang teilweise sehr unterscheidet. Standardmäßig stehen bei folgenden Windowsversionen folgende Powershell-Versionen zur Verfügung.
Vista / Windows 2008 - 1.0
Windows 7 / Windows 2008 R2 - 2.0
Windows 8 / Windows 2012 - 3.0
Windows 8.1 / Windows 2012 R2 - 4.0
Man kann aber auch abweichende Versionen installieren. So ist es beispielsweise möglich unter XP Version1.o oder 2.o zu installieren bzw. unter Windows 7 4.0.
Die installierte Version kann man mittels > $PSVersionTable herausfinden.
siehe auch:
Where-Object{$_.XYZ -eq "ABC"}
Schleifen
if / select case (switch) - bedingte Anweisung
How Can I Evaluate a Condition and Select from Several Options with Windows PowerShell?
Anzahl: get-command | measure-object oder (get-command).count
> running scripts is disabled at this system
Lösung: Set-ExecutionPolicy RemoteSigned
>The term 'test.ps1' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
Lösung: .\test.ps1
ohne Punkt \ können nur Skripte ausgeführt werden, die im PATH-environment liegen. Dies kann man folgendermaßen prüfen.
$a = $env:path; $a.Split(";")
Um einen weiteren Pfad in das PATH-environment zu bekommen:
$env:path = $env:path + ";c:\scripts"
>Access to a CIM resource was not available to the client
Der Zugriff auf das Common Information model (CIM) erfordert Admin-Rechte.
siehe auch:
Basisprobleme:
CIM resource
Module eignen sich hervorragend um Funktionen auszulagern.
Load Module if not loaded
$ModuleName = "Folder2ISO"$Module2Load = $PSScriptRoot + $ModuleName +".psm1"if (!(Get-Module -Name $ModuleName)) { Write-Host "Lade Modul $Module2Load" Import-Module $Module2Load }
siehe auch:
is Null or Emtpy
clsWrite-host "is Null or Emtpy" -BackgroundColor Yellow -ForegroundColor Red#Funktionenfunction IsNullOrEmpty($myString) { if ($myString) {return,$false} else {return,$true} } function IsNullOrEmpty2($myString) { if ($myString) { if ($myString.trim().length -eq 0) { return,$true } else { return,$false } } else { return,$true } } #BeispieleWrite-Host "Beispiel: NULL" -ForegroundColor Green$str = $null IsNullOrEmpty($str) #trueIsNullOrEmpty2($str) #true[string]::IsNullOrEmpty($str) #true$str = ''Write-Host "Beispiel: EMPTY" -ForegroundColor Green IsNullOrEmpty($str) #trueIsNullOrEmpty2($str) #true[string]::IsNullOrEmpty($str) #trueWrite-Host "Beispiel: SPACES" -ForegroundColor Green$str = ' ' IsNullOrEmpty($str) #falseIsNullOrEmpty2($str) #true[string]::IsNullOrEmpty($str) #falseWrite-Host "Beispiel: REAL String" -ForegroundColor Green$str = 'test' IsNullOrEmpty($str) #falseIsNullOrEmpty2($str) #false[string]::IsNullOrEmpty($str) #false
die wichtigsten Textbearbeitungsfunktionen sind:
Trim() / TrimEnd() / TrimStart()
SubString()
Contains()
ToLower() / ToUpper()
StartsWith() / EndsWith()
> $DirectoryName.StartsWith("_")
siehe auch:
Text in Datei ersetzen
(Get-Content $file.FullName | ForEach { ($_ -replace "oldtext", "newtext") }) | Set-Content $file.FullName
siehe auch:
Zeitstempel/Datumsstempel/TimeStamps/DateStamps
Bsp: $(get-date -f yyyyMMddhhmmss)
$myfile = (Get-Item -Path $myfilepath)
Copy-Item $myfile.FullName (Join-Path -Path (Split-Path -parent $myfile.FullName) -ChildPath ($myfile.BaseName + "_" + $(get-date -f yyyyMMddhhmmss) + $myfile.Extension))
Beispiel:
$cmd='c:\windows\system32\xcopy.exe'
$from='f:\test'
$to='f:\test 123\'
$switches='/s/y'
&$cmd "$from" "$to" $switches
weitere Links:
[TechNet] PowerShell: Running Executables (hervorragende Webseite)
Links:
create-local-user.ps1
function CreateLocalUser([string]$username, [string]$password, [bool]$restricted) { #Check User exits $founduser = get-WmiObject Win32_UserAccount | Where-Object{$_.name -eq $username} if ($founduser -eq $null) { Write-Host "User not exits -> Create User" -ForegroundColor Yellow Write-Host "Username: $username" Write-Host "Password: $password" $server=[adsi]"WinNT://$env:computername" $user=$server.Create("User",$username) $user.SetPassword($password) $user.SetInfo() # add extra info if ($restricted -eq $true) { $user.Put('Description','Limited user account') $flag=$user.UserFlags.Value -bor 0x800000 $user.put('userflags',$flag) $user.SetInfo() } Write-Host "User $username erstellt" -ForegroundColor Red #Check Again User exists $founduser = get-WmiObject Win32_UserAccount | Where-Object{$_.name -eq $username} if ($founduser -eq $null) { return,$false } else { return,$true } } else { Write-Host "User already exits" -ForegroundColor Red return,$false } } CreateLocalUser -username "Usnername" -password "meinPasswort" -restricted $true
Anmerkung: Damit alleine kann der User sich noch nicht am Rechner einloggen. Dafür muss er zusätzlich in der lokalen Gruppe "users" eingetragen sein. (siehe dazu unten)
Alternativen:
Für lokale Benutzer kann der "alte" Befehl net user auch eingesetzt werden:
NET USER username "password" /ADD
Alternativ kann man auch auf das Powershell Modul Carbon zurückgreifen.
Alternativen:
Auch hier - ebenso wie beim lokalen Benutzer - besteht die Möglichkeit mittels net localgroup ohne powershell schnell zum Ergebnis zu kommen.
NET LOCALGROUP "group" "user" /add
Alternativ kann man auch auf das Powershell Modul Carbon zurückgreifen.
Siehe Download-File "create-local-user-that-is-allowed-to-log-in.ps1"
Autologin.ps1
#Hauptfunktionfunction AutoLogin([string]$username, [string]$userpassword) { Write-Host "AutoLogin" Write-Host "Username: $username" Write-Host "Password: $userpassword" $AutoLoginKey = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" ChangeRegistryValue -path $AutoLoginKey -key "AutoAdminLogon" -value "1" ChangeRegistryValue -path $AutoLoginKey -key "DefaultUserName" -value $username ChangeRegistryValue -path $AutoLoginKey -key "DefaultPassword" -value $userpassword Write-Host "Autologin enabled" -Foreground Green } #Hilfsfunktionenfunction ChangeRegistryValue($path, $key, $value) { Write-Host "Change $path $key to $value" if (Test-RegistryValue $path $key) { Write-Host "$key exits - Change it" -Foreground Green Set-ItemProperty -Path $path -Name $key -Value $value } else { Write-Host "$myname not exits - Create it" -Foreground Green New-ItemProperty -Path $path -Name $key -Value $value } Write-Host "Registry $key changed to $value" } function Test-RegistryValue($path, $name) { $key = Get-Item -LiteralPath $path -ErrorAction SilentlyContinue $key -and $null -ne $key.GetValue($name, $null) } AutoLogin -username "Username" -userpassword "myPassword"
manuelle Anleitung: siehe dazu RemoteDesktop & Virtualisierung
Fall 1: man ist auf dem Rechner eingeloggt, auf dem man die Remote Desktop Funktion freischalten möchte
Die Freischaltung der Remote Desktop-Funktionalität umfasst 3 Schritte:
1. Remote Desktop erlauben
2. Benutzer definieren, die zugreifen dürfen
3. Firewall entsprechend konfigurieren
Links dazu:
Fall 2: man möchte Remote die Remote Desktop Funktion freischalten
siehe dazu
Alternativ kann man auch die Module "Set-RemoteDesktop" von hier verwenden.
Eine weitere Alternative stellt die Konfiguration über SCONFIG dar.
siehe [powershell] Shutdown / Wake Up Computer remote
Achtung: Bug bei Dateinamen mit square brackets / eckigen Klammern / [ ] - siehe: hier
zum square brackets Problem auch: hier (Taking Things (Like File Paths) Literally)
Generell kann man das Problem durch die Verwendung von -LiteralPath anstelle von -Path meist umgehen.
Ausnahmen:
Rename-Item hat keinen -LiteralPath Parameter => stattdessen kann man Move-Item verwenden. (seit V3 hat Rename-Item auch einen -LiteralPath Parameter)
Get-ChildItem -LiteralPath <Path mit []> liefert auch einen Fehler
Als Workaround gibt es die Möglichkeit alle [] aus Ordnernamen (ausgehend von einem Startverzeichnis zu entfernen)
entfernen aller eckigen Klammern
function removeSquareBrackets([string]$StartDir) { $re = "[\[\]]"$currItem = (Get-Item -LiteralPath $StartDir) if ($currItem.Name -match $re) { $newitem = (Join-Path -Path (Get-Item $currItem.PSParentPath) -ChildPath ($currItem.Name -replace $re,"")) Rename-Item -LiteralPath $currItem.FullName -NewName $newitem $currItem = (Get-Item -LiteralPath $newitem) } dir -LiteralPath $currItem.FullName -Recurse | ?{$_.Name -match $re} | %{ren -literalpath $_.FullName -newname (join-path (get-item $_.PSPArentPath) $($_.Name -replace $re,""))} return,$currItem.FullName }
Join-Path -Path dir -ChildPath document
Das Childpath-Element und auch das Path-Element dürfen nur 1x verwendet werden.
Test-Path docs\readme.txt
Datei/Verzeichnis existiert
# Prüfen ob eine Datei existiert$Data = "D:\Order\Ein_Text_File.txt"If (Test-Path $Data) { Write-Host "Die Datei $($Data) existiert bereits." } else { Write-Host "Die Datei $($Data) existiert nicht." } # Prüfen ob ein Verzeichnis existiert$Dir = "D:\Order\"If (Test-Path $Dir) { Write-Host "Der Ordner $($Dir) existiert." } else { Write-Host "Der Ordner $($Dir) existiert nicht." }
weiterführende Links
Order (parent) ermitteln
$filename = "C:\Test\text.txt"$file = (Get-Item $filename) $parent = $file.Directory.BaseName Write-Host $parent
Alternative:
function getParent([string]$currdir, [int]$parentcounter = 1) { $tmpDir = $currdir for ($i=1; $i -le $parentcounter; $i++) { if ($tmpDir.length -gt 3) { $tmpDir = (get-item $tmpDir ).parent.FullName } else { break } } return,$tmpDir } $parent = (getParent -currDir "g:\t\t\t\t\" -parentcounter 3) Write-Host "Parent-Folder: $parent"
es geht aber auch schneller:
Split-Path -parent $filepath
Split-Path -parent $file.Fullname
Basisbefehl: Get-Childitem
Anwendung von Get-Childitem
$StartDir = "g:\tt\"#alle Ordner auflistenWrite-Host "Verzeichnisse/Order auflisten" -ForegroundColor DarkGreenGet-ChildItem -Path $StartDir -Directory | Select-Object FullName#alle Dateien auflistenWrite-Host "Dateien auflisten" -ForegroundColor DarkGreenGet-ChildItem -Path $StartDir -File#alle Dateien eines bestimmten DateitypsWrite-Host "Dateien eines bestimmten Typs auflisten" -ForegroundColor DarkGreenGet-ChildItem -Path "$StartDir\*.jpg" -FileWrite-Host "Alternative:"Get-ChildItem -Path "$StartDir\*" -File -Include "*.jpg"#alle Dateien außer die eines bestimmten DateitypsWrite-Host "Dateien außer die eines bestimmten Dateityps" -ForegroundColor DarkGreen# NICHT: Get-ChildItem -Path $StartDir -File -Exclude "*.jpg"Get-ChildItem -Path "$StartDir\*" -File -Exclude "*.jpg"Write-Host "das geht auch mit mehreren Dateitypen"$exclude = @("*.jpg", "*.jpeg") Get-ChildItem -Path "$StartDir\*" -File -Exclude $excludeWrite-Host "das geht auch mittels einer Pipe der Ergebnisse"$exclude = @(".jpg", ".jpeg") Get-ChildItem -Path "$StartDir\*" -File | Where-Object {$exclude -notcontains $_.Extension} #nur bestimmte Eigenschaften anzeigen -ForegroundColor DarkGreenWrite-Host "nur bestimmte Eigenschaften anzeigen" -ForegroundColor DarkGreenGet-ChildItem -Path "$StartDir\*" -File | ft Name, FullName, Extension, length #Auflisten aller leeren VerzeichnisseWrite-Host "alle leeren Verzeichnisse auflisten" -ForegroundColor DarkGreen (Get-ChildItem $StartDir -recurse | Where-Object {$_.PSIsContainer -eq $True}) | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName#Auflisten von Dateien/Ordnern mit einem bestimmten Namensbestandteil$String2Search = "*XYZ*"Write-Host "Dateien mit bestimmten Namen ('$String2Search') suchen" -ForegroundColor DarkGreenWrite-Host "Dateien" -BackgroundColor Yellow#DateienGet-ChildItem -Path $StartDir -Filter $String2Search -File | Select-Object FullName#VerzeichnisseWrite-Host "Verzeichnisse" -BackgroundColor YellowGet-ChildItem -Path $StartDir -Filter $String2Search -Directory | Select-Object FullName
weiterführende Links:
Datum (Erstelldatum, Änderungsdatum)
Datumsfilter
$StartDir = "G:\test\" [int]$days = 2#Ordner mit Erstellungsdatum und Änderungsdatum auflistenWrite-Host "List all Directories" -ForegroundColor RedGet-ChildItem $StartDir | ft FullName, CreationTime, LastWriteTime#Ordner, die in den letzten 2 Tagen nicht geändert wurdenWrite-Host "List all Directories not changed in the last $days days" -ForegroundColor RedGet-ChildItem $StartDir -Directory | Where {$_.lastwritetime -lt (get-date).adddays(-$days)} | ft FullName, CreationTime, LastWriteTime#Ordner, die in den letzten 2 Tagen erstellt wurdenWrite-Host "List all Directories created in the last $days days" -ForegroundColor RedGet-ChildItem $StartDir -Directory | Where {$_.CreationTime -gt (get-date).adddays(-$days)} | ft FullName, CreationTime, LastWriteTime#Dateien, die in den letzten 2 Tagen nicht geändert wurdenWrite-Host "List all Files not changed in the last $days days" -ForegroundColor RedGet-ChildItem $StartDir -File -Recurse | Where {$_.lastwritetime -lt (get-date).adddays(-$days)} | ft FullName, CreationTime, LastWriteTime#Ordner, die Dateien enthalten, deren LastWriteTime neuer als 2 Tage istWrite-Host "List all Folders with Files newer than $days days" -ForegroundColor Red$dirs2check = Get-ChildItem $StartDir -Directory foreach ($dir2check in $dirs2check) { $foundfiles = Get-ChildItem $dir2check.FullName -File -Recurse | Where {$_.lastwritetime -gt (get-date).adddays(-$days)} if ($foundfiles.count -gt 0) { Write-Host "Verzeichnis " $dir2check.FullName " enthält Datei, die neuer sind als $days Tage" -ForegroundColor DarkMagenta #Get-ChildItem $dir2check.FullName -File -Recurse | Where {$_.lastwritetime -gt (get-date).adddays(-$days)} | ft FullName, CreationTime, LastWriteTime } }
Erstellen eines Ordners:
> New-Item -ItemType directory -Path C:\Scripts\newDir
Erstellen einer Datei
> New-Item c:\scripts\new_file.txt -type file
Wenn die/der Datei/Ordern bereits existiert, dann bekommt man eine Fehlermeldung, wie beispielsweise
New-Item : The file 'C:\scripts\new_file.txt' already exists.
Bei Dateien kann man erzwingen, dass diese überschrieben werden
> New-Item c:\scripts\new_file.txt -type file -force
Links:
Datei löschen, sofern sie existiert
Function Delete-File([string]
Order mit inhalt (leise [dh. ohne Rückfrage]) löschen:
Löschen einer Datei in den Papierkorb
Aufruf: delete2recyclebin.ps1 -file "C:\test\test.txt"
delete2recyclebin.ps1
#Verschiebt eine Datei in den Papierkorbparam( [string]$file ) $path = $fileWrite-Host "Delete File '$file' (with Recycle Bin)"$shell = new-object -comobject "Shell.Application"$item = $shell.Namespace(0).ParseName("$path") $item.InvokeVerb("delete")
Recycle Bin:
.Length = Dateigröße
Dateigröße:
Example FileSize
filePath = "D:\Path\File.ext"if (Test-Path $filePath) { #if File exists $fileSize = (Get-Item $filePath).length #FileSize Write-Host "$filePath hat eine Dateigröße von $fileSize" } else { Write-Host "$filePath wurde nicht gefunden" }
als Funktion mit Parameter für KB,MB,GB,TB
getFileSize
function getFileSize([string]$filePath, [string]$SizeType) { if (Test-Path $filePath) { #if File exists $fileSize = (Get-Item $filePath).length #FileSize switch ($SizeType) { "KB" { $fileSize = $fileSize/1KB } "MB" { $fileSize = $fileSize/1MB } "GB" { $fileSize = $fileSize/1GB } "TB" { $fileSize = $fileSize/1TB } default {$fileSize = $fileSize/1} } } else { $fileSize = 0 } return,$fileSize } $filePath = "D:\Folder\File.ext"$myFileSize = getFileSize -filePath $filePathWrite-Host $myFileSize$myFileSize = getFileSize -filePath $filePath -SizeType "GB"Write-Host $myFileSize
Ordergröße
getFolderSize
function getFolderSize([string]$folderPath, [string]$SizeType, [bool]$subfolder) { if ($subfolder -eq $null) { $subfolder = $true } if (Test-Path $folderPath) { #if Folder exists # Calculate FileSize if ($subfolder -eq $true) { $colItems = (Get-ChildItem $folderPath -Recurse | Measure-Object -property length -sum) } else { $colItems = (Get-ChildItem $folderPath | Measure-Object -property length -sum) } $fileSize = $colItems.sum switch ($SizeType) { "KB" { $fileSize = $fileSize/1KB } "MB" { $fileSize = $fileSize/1MB } "GB" { $fileSize = $fileSize/1GB } "TB" { $fileSize = $fileSize/1TB } default {$fileSize = $fileSize/1} } } else { #if Folder not exists $fileSize = 0 } return,$fileSize } $myFolder = "D:\Folder"$myFolderSize = getFolderSize -folderPath $myFolderWrite-Host "Gesamtgröße: $myFolderSize"$myFolderSize = getFolderSize -folderPath $myFolder -SizeType "TB" -subfolder $trueWrite-Host "Gesamtgröße in TB: $myFolderSize"
weiterführende Links:
Verzeichnisse vergleichen
Verzeichnisse vergleichen mittels MD5
Order umbenennen, sofern sie bestimmte Dateien beinhalten
RenameFolderIfContains
function RenameFolderIfContains([string]$StartDir, [string]$Filter, [string]$append, [bool]$quiet) { #if quiet missing if ($quiet -eq $null) {$quiet = $false} #Get all Directories $Directories = Get-ChildItem -Path $StartDir -Directory #Create Array $dynArray = @() $Directories | ForEach-Object { if (!($_.FullName.Trim().EndsWith($append))) #Exclude Folders with the $append-Text { $currDir = $_.FullName #Get Full Path if ($quiet -eq $false) {Write-Host "aktuelles Verzeichnis: $currDir"} $files = Get-ChildItem -Path $currDir -Filter $Filter if (!($files -eq $null)) { if ($quiet -eq $false) {Write-Host " Dateien gefunden in '$currDir'"} $dynArray += $currDir } else { if ($quiet -eq $false) {Write-Host " keine Datei gefunden in '$currDir'"} } } } if ($quiet -eq $false) {Write-Host "betroffene Verzeichnisse:" -ForegroundColor Red -BackgroundColor Yellow} foreach ($element in $dynArray) { if ($quiet -eq $false) {Write-Host "- Bearbeite Verzeichnis: $element"} $targetname = (Split-Path ($element) -Leaf) + " " + $append if ($quiet -eq $false) {Write-Host " benenne um von '$element' in '$targetname'"} Rename-Item -Path $element -NewName $targetname } } RenameFolderIfContains -StartDir "f:\HomeVideos\" -Filter "*.iso" -append "@" -quiet $true
[RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape(-join [System.IO.Path]::GetInvalidFileNameChars())), '')
siehe auch:
Ein sehr gutes Skript zum Entpacken findet man hier.
Download Website
$ie = New-Object -com InternetExplorer.Application $ie.visible = $true$ie.navigate($myWebsite) while($ie.ReadyState -ne 4) { start-sleep -s 10 } $ie.Document.Body |Out-File D:\test1.html$ie.Quit()
Umgang mit Arrays
$a = @{} # hash$a = @() # array ######################################### ######### ARRAY ######### #########################################Write-Host "----- ARRAYS -----" -BackgroundColor DarkBlue -ForegroundColor White$arr=@() #Create empty Array$arr=@("Test1", "test2", "Test3") #Create an array with Values#Split Text in Array$address = "Text1A; Text2A; Text3A; Text4A"# Alternative 1$addresses = $address -split "; "# Alternative 2$addresses = $address.replace(' ','').split(';') #Check Array ElementsWrite-Host "Check Array contains" -BackgroundColor Yellow#Contains is not case sensitiveWrite-Host "Check Array contains - not casesensitive" -BackgroundColor Gray$arr -contains "Test3" #Case Sensitive$arr -contains "test3" #Case Sensitive$arrElement = $arr -contains "Test3"#Case sensitive checkWrite-Host "Check Array contains - casesensitive" -BackgroundColor Gray$arr -ccontains "Test3" #Case Sensitive$arr -ccontains "test3" #Case Sensitive #likeWrite-Host "Check Array contains - like" -BackgroundColor Gray$arr -like "Test*"#Add to ArrayWrite-Host "Add Element to Array" -BackgroundColor Yellow$arr += "Test4new"Write-Host "Add Array to Array" -BackgroundColor Yellow$arr = $arr + $addresses#Set Item of Array$arr[2] = "Changed Item"#ArraylängeWrite-Host "Array Länge" -BackgroundColor YellowWrite-Host $arr.length Write-Host "First Element: 0" -BackgroundColor Yellow [int]$len = $arr.length $len = $len - 1Write-Host $lenWrite-Host "Last Element: $len" -BackgroundColor Yellow#Accessing Values of Array #Source: http://technet.microsoft.com/en-us/library/ee692791.aspx #every elementWrite-Host "Loop through Array - Variante 1" -BackgroundColor Yellowforeach ($y in $arr) {$y} Write-Host "Loop through Array - Variante 2" -BackgroundColor Yellowfor ($i=0;$i -le $len; $i++) { $arr[$i] } #certain arraywrite-host "Access certain element" -BackgroundColor YellowWrite-Host $arr[3] #Array sortieren$arr = $arr | Sort-Object#Deleting ArrayRemove-Item variable:arr ######################################### ######### HASH ######### #########################################Write-Host "----- HASH -----" -BackgroundColor DarkBlue -ForegroundColor White$arr=@{} #Create empty Hash$arr["david"] = @{} $arr["david"]["TSHIRTS"] = @{} $arr["david"]["TSHIRTS"]["SIZE"] ="M"$arr.david.tshirts.size #Quelle: http://stackoverflow.com/questions/9397137/powershell-multidimensional-arrays
Für automatisches Starten von Powershell Skripten eignet sich der Task Sheduler von Windows. Wie man dort einen neuen Task erstellt, erfährt man hier (How to Schedule a PowerShell Script)
Custom-Object
meine Powershell-Bibliothek: hier