IT-Wissen/powershell
2024-10-14 22:37:09 +02:00
..
README.md powershell 2024-10-14 22:37:09 +02:00

Table of Contents

PowerShell

Installation Ubuntu

https://learn.microsoft.com/en-us/powershell/scripting/install/install-ubuntu?view=powershell-7.4

Einführung

get version

Get-Host | Select-Object Version

Objekte mit Properties und Methoden

Alle Cmdlets (Commandlets) sind Objekte. Da die PowerShell auf dem .NET Framework basiert, arbeitet sie durchgehend mit Objekten. Jedes Resultat eines ausgeführten Cmdlets ist ein Objekt, also eine Instanz einer .NET-Klasse oder einer .NET-Collection. Somit kann mit der bekannten Punktnotation auf Members des Objekts, wie Properties oder Methoden, zugegriffen werden.

Gibt das Datum in voller Länge aus. Es ist ein Objekt:

Get-Date

Zeigt alle Properties und Methoden des Objekts an:

Get-Date | Get-Member

Zugriff auf Property Year:

(Get-Date).Year

Zugriff auf Methode ToLongTimeString()

(Get-Date).ToLongTimeString()

Kommentare

# einzeilig

<# ein
block #>

PS Special-Characters

Alle Special-Charakter von Powershell auf einen Blick

PowerShell-Provider

Auflisten aller Provider, wie Registry, Umgebungsvariablen, Variablen, Funktionen etc.

Get-PSProvider


Name                 Capabilities                                    Drives
----                 ------------                                    ------
Registry             ShouldProcess, Transactions                     {HKLM, HKCU}
Alias                ShouldProcess                                   {Alias}
Environment          ShouldProcess                                   {Env}
FileSystem           Filter, ShouldProcess, Credentials              {C, H, J, K...}
Function             ShouldProcess                                   {Function}
Variable             ShouldProcess                                   {Variable}
Certificate          ShouldProcess                                   {Cert}
WSMan                Credentials                                     {WSMan}

Sie werden wie Drives verwendet. Man kann z.B. wechseln mit cd Env: # immer mit Doppelpunkt

Datentypen

Datentypen müssen nicht zwingend angegeben werden, können aber:

[Array]             Array
[Bool]              Wert ist TRUE oder FALSE
[DateTime]          Datum und Zeit
[Guid]              Global eindeutige 32-Byte ID
[HashTable]         Hash-Tabelle, Sammlung von Schlüssel-Wert-Paaren
[Int32], [Int]      32-bit Integer
[PsObject]          PowerShell-Objekt
[Regex]             Regular expression
[ScriptBlock]       PowerShell script block
[Single], [Float]   Fließkommazahlen
[String]            Zeichenkette
[Switch]            PowerShell Switch-Parameter
[TimeSpan]          Zeitintervall
[XmlDocument]       XML-Dokument

Datentyp ermitteln

$t = "bla"; $t.getType()

Variablen und Arrays

Variable

Variablen beginnen mit Dollar $

Zuweisung mit =

$files = Get-ChildItem c:\xampp\htdocs -Recurse | Sort-Object Length -Descending | Select-Object Fullname, Length -First 5

$()

Anweisung in () werden zuerst ausgeführt.

$name = "Kevin"; "Hello, $name, there are $($name.length) characters in your name"

$_

THIS, typischerweise in einer foreach Schleife

$

Declare or use a variable with non-standard characters in it

${,&} = 5

Arrays

Siehe auch hier

leeres Array erstellen

$t = @()

Werte an Array zuweisen

# vermischte Datentypen:
$t = "a","b",22

# Alternativ ("richtig"):
$t = @("a","b",22)

# mit Typenbegrenzung:
[Int[]]$t=2,1

Bei Strings wird ohne Angabe des Datentyps ein Object gemacht. Siehe $variable.getType()

Array erweitern

$t += 3

Länge eines Arrays

$t.Length

2 Arrays zusammenführen

$u = "a","b","c"; $u2 = "d","e"; $u += $u2

Element in Array über Index ansprechen

$t[0]
$t[0,3,5]
$t[1..3]

Array Element finden

$a = "aaa","bbb","ccc","ddd"
$a -contains "aaa"  # liefert TRUE. -ccontains berücksichtigt Gross-/Kleinschreibung

# oder

$a -like "aa*"  # gibt Wert zurück (kein Boolean wie oben)

# oder

$a.Where{$_ -like "bbb"}
# siehe Where Parameter wie skipUntil oder last.

Array Elemente sortieren

$t | sort

Array Elemente löschen

Möchte man einzelne Elemente entfernen, dann muss man den Umweg über das Filtern und Neuzuweisen gehen:

$a = $a | where {$_ -ne "aaa"}

Array löschen

$t = $null

Array ausgeben

$a[0] -join ',' 
#oder
$array -join '|'

Ausgabe

echo und Write-Output ist das selbe. Kann für Weiterverarbeitung verwendet werden. Write-Host nur für Ausgabe in Console.

Vorbereitung für dieses Tutorial

$files = Get-ChildItem c:\xampp\htdocs -Recurse | Sort-Object Length -Descending | Select-Object Fullname, Length, CreationTime -First 5
$files2 = Get-ChildItem c:\xampp\htdocs -Recurse | Sort-Object Length -Descending | Select-Object -First 25

Txt Datei auslesen

Get-Content -Path C:\Test\ServerNames.txt
# UTF-8 encodiert:
Get-Content -Encoding UTF8 -Path C:\Test\ServerNames.txt

Ausgabe in TXT speichern

Write-Output "hallÖ" | Out-File c:\Roger\hallo.txt -Encoding UTF8

# oder einfacher:
"hallÖ" > C:\Roger\hallo.txt

Ausgabe als CSV speichern

$files | Export-Csv c:\Roger\files.csv

Ausgabe als JSON speichern

$files | ConvertTo-Json | Out-File c:\Roger\files.json

Ausgabe als HTML speichern

$files | ConvertTo-Html | Out-File c:\Roger\files.html

Ausgabe in Windows-Presentation-Foundation (WPF)

$files | Out-GridView

Ausgabe filtern

Im Beispiel sollen alle Windows-Services angezeigt werden, welche den Status Running besitzen und den Text Network im Namen enthalten:

Get-Service | Where-Object {($_.Status -eq "Running") -and ($_.Name -match "wpn")}
$files | Where-Object {$_.Length -lt 20000000}
$files | Where-Object {(Get-Date $_.CreationTime) -lt (Get-Date 20.05.2015)}

($_ enthält den Wert des in der Schlaufe durchlaufenen Objekts)

Filtermöglichkeiten:

Gleich (equal): 								-eq
Ungleich (not equal): 							-ne
Kleiner (less than): 							-lt
Kleiner oder gleich (less than or equal): 		-le
Größer (greater than): 							-gt
Größer oder gleich (greater than or equal): 	-ge
Enthält (contains): 							-contains
Enthält nicht (not contains): 					-notcontains
Ähnlich (like): -like, 							-notlike
Match (match/notmatch) für regex: 				-match, -notmatch
Ersetzen (replace): 							-replace

Sortierung (Alternativ zu Sortierung bei der Abfrage, bei "Vorbereitung")

$files2 | Sort-Object CreationTime | Format-List Fullname, Length, CreationTime

Sortierung mit Unique

$files2 | Sort-Object CreationTime -Unique | Format-List Fullname, Length, CreationTime

Gruppierung

$files2 | Format-List Fullname, Length, CreationTime -GroupBy CreationTime

Ausgabe formatieren

# Ausgabe als Tabelle (Standard). Hierzu ist es nötig, die Felder bei der Abfrage schon angegeben zu haben (Fullname, Length, CreationTime)
$files  # ist das gleiche wie:
$files | Format-Table  # oder
$files | ft
# Ausgabe als Liste
$files | Format-List  # oder, wenn Felder bei Abfrage noch nicht angegeben:
$files2 | Format-List                                   # Standard-Felder
$files2 | Format-List *                                 # Alle möglichen Felder
$files2 | Format-List Fullname, Length, CreationTime    # nur die benötigten Felder

Write-Host

Formatierung

Mit Write-Host kann die Ausgabe noch weiter formatiert werden

# Farben:
Get-Content -Encoding UTF8 -Path C:\Roger\regex-examples.txt | Write-Host -BackgroundColor("DarkGray")

# ohne neue Linien:
Write-Host "aaaaa" -NoNewline; Write-Host "bbbbbb"

# Separator für Array Elemente:
Write-Host (1,44,"abc",9) -Separator "|"

Ausgabe von Zeichen, die als PS Befehle interpretiert werden könnten

# mit --%
Write-Host --% %USERNAME%,this=$something{weird}

# zum Vergleich:
Write-Host %USERNAME%,this=$something{weird}

Vergleichsoperatoren

Zahlen

-eq gleich
-ne ungleich
-lt kleiner
-le kleiner oder gleich
-gt größer  # bsp: "Dies ist ein Text".length -gt 10  # ergibt TRUE
-ge größer oder gleich

Strings

  • -like / -notlike mit oder ohne Wildcards "PowerShell" -like "Pow*"
  • -contains / -notcontains für Arrays. "Dezember","Januar","Februar" -contains "Februar"
  • -match / -notmatch "PowerShell" -match "ower"

Arbeiten mit Text

Letztes Zeichen löschen

$a = $a.Substring(0, $a.Length - 1)

# falls noch geprüft werden muss, ob das letzte Zeichen ein | ist:
if ($a.LastIndexOf("|") -eq ($a.Length - 1)) {
	$a = $a.Substring(0, $a.Length - 1)
}

Random String aus Buchstaben/Zahlen generieren

# mit 12 Zeichen:
$randomString = -join (((48..57)+(65..90)+(97..122)) * 80 |Get-Random -Count 12 |%{[char]$_})

Erhalte Text zwischen zwei Zeichen in einem String

$b = $FolderPath.LastIndexOf("/")
$b = $FolderPath.LastIndexOf("/", $b - 1)
$a = $FolderPath.LastIndexOf("/", $b - 1)
$a++
$derGesuchteText = $FolderPath.SubString($a, $b - $a) 

Lese Datei aus und zeige alle 2-stelligen Zahlen an (regex)

$regex = [regex]"\b\d\d\b"
Select-String -Path C:\Roger\zahlentest.txt -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }

# oder regex direkt in Anweisung:
Select-String -Path C:\Roger\zahlentest.txt -Pattern "\b\d\d\b" -AllMatches | % { $_.Matches } | % { $_.Value }

# zusätzlich als Datei speichern:
Select-String -Path C:\Roger\zahlentest.txt -Pattern "\b\d\d\b" -AllMatches | % { $_.Matches } | % { $_.Value } > C:\Roger\zahlentest_output.txt

IPs oder URLs aus TXT herauslesen und auflisten (regex)

# Erstellen wir zuerst eine TXT-Datei, z.B. aus einem tracert.exe Befehl:
TRACERT.EXE fuw.ch | Out-File c:\Roger\tracert-fuw-ch.txt -Encoding UTF8

# Nun das Auslesen:
Select-String -Path C:\Roger\tracert-fuw-ch.txt -Pattern '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' -AllMatches | % { $_.Matches } | % { $_.Value } > C:\Roger\tracert-fuw-ch-only-ips.txt

## URL's
$regex = '([a-zA-Z]{3,})://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)*?'

Arbeiten mit Zahlen

Modulo (Remainder of a Division)

5 % 2

Kontrollstrukturen

if then else

if($test) {
    echo "Value of test: " $test}
else {
    echo "Value of test is zero or undefined"
}

# Boolean gegenteilig prüfen: mit ! davor.

$a="xyz"; $b="b"
if($a -like "a") {
    echo "a OK"
} elseif($b -like "b") {
    echo "b OK"
} else {
    echo "else"
}

switch

switch is used for testing equality only. Thus, you can't use comparison operators in switch statements.

switch(Read-Host "Select a menu item"){
    1 {"File will be deleted"}
    2 {"File will be displayed"}
    3 {"File is write protected"}
    default {"Invalid entry"}
}
# wenn bei einem match nicht mehr weiter gesucht werden soll, muss break angefügt werden:
    1 {"File will be deleted"; break}
# switch mit wildcards
switch -wildcard("PowerShell"){
    "Power*" {echo "'*' stands for 'shell'"}
    "*ersh*" {echo "'*' replaces 'Pow' and 'ell'"}
    "PowerShe?" {echo "Pattern matches because ?? replaces two 'l' "}
}

for loop

$colors = @("Red","Orange","Yellow","Green","Blue","Indigo","Violet")
For ($i=0; $i -lt $colors.Length; $i++) {
    $colors[$i]
}

foreach loop

$myDocuments = Get-ChildItem C:\Roger -File

# Ausgabe mit foreach:
foreach($ele in $myDocuments) { $ele.FullName }

# Ausgabe mit Pipe:
$myDocuments | ForEach-Object {$_.FullName}

# oder Ausgabe mit -InputObject:
ForEach-Object -InputObject $myDocuments {$_.FullName}

# Shorthands:
Get-WMIObject Win32_LogicalDisk | ForEach-Object {$_.FreeSpace}
Get-WMIObject Win32_LogicalDisk | ForEach {$_.FreeSpace}
Get-WMIObject Win32_LogicalDisk | % FreeSpace

# gleich wie
foreach($ele in Get-WMIObject Win32_LogicalDisk) { $ele.FreeSpace }

all loops explained

https://www.gngrninja.com/script-ninja/2016/4/20/powershell-getting-started-part-5-loop-the-loop#dountil

Objekt zählen

($svgs | measure).Count

Datum / Zeit

Anzahl Tage von einem bestimmten Datum bis heute

[DateTime]$Date = "28. February 2015"
$Today = Get-Date
$Days = ($Today - $Date).Days
Write-Host "Vergangene Tage seit" $Date":" $Days

Dateien

Hash aus Datei generieren

get-filehash -algorithm sha512 .\SAB_2018-03-29_Einzelstuecke.pdf

Die 5 grössten Dateien in einem Verzeichnis auflisten (rekursiv)

Get-ChildItem c:\xampp -Recurse | Sort-Object Length -Descending | Select-Object Fullname, Length -First 5

Show files larger than X

Get-ChildItem -Path C:\ -File -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.Length -gt 2GB} | Sort-Object length -Descending | Select-Object Name,Directory,@{n='GB';e={"{0:N2}" -F ($_.length / 1GB)}} | Out-GridView -Title "Large Files"

Datei-Liste, sortiert

# This command sorts text files in descending order by the time span between CreationTime and LastWriteTime.
Get-ChildItem -Recurse -Path C:\Roger\*.txt | Sort-Object -Property @{Expression = {$_.CreationTime - $_.LastWriteTime}; Descending = $True} | Format-Table CreationTime, LastWriteTime, FullName

Klassen

Aufruf von Static Methode einer Klasse

The class name must be enclosed in square brackets.

[string]::Equals("a", "b")

Powershell als Datei

Dateiendung .ps1

Aufruf

& script.ps1

# oder als Verknüpfung
powershell.exe -File c:\roger\script.ps1

# Allenfalls noch Rechte setzen:
Set-ExecutionPolicy RemoteSigned

# Restricted — Stops any script from running.
# RemoteSigned — Runs scripts created on the device. However, scripts created on another computer won't run unless they include a signature of a trusted publisher.
# AllSigned — All the scripts will run as long as they've been signed by a trusted publisher.
# Unrestricted — Runs any script without any restrictions.

# in konsole dauerhaft (pro session):
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Externes Script einbinden

#line 1 of your script
. ./script.ps1 #include from current directory
#line 2
#use function or variable from script.ps1

Beispiel PS-Schnippsel

Find encrypted files

$path=$args[0]
Write-Host "checking: $path"
$p = Get-ChildItem -Path $path -Recurse -Force -Attributes Encrypted

if ($p) {
  Write-Host "Found" $p.Name.Count "encrypted files"
  Write-Output $p.Name
  exit 1
}
else {
  Write-Host "No encrypted files found"
  exit 0
}

Find password protected zip files

# check for password protected ZIP archives
Get-ChildItem -Path $path -Recurse -Filter *.zip | Where-Object { ` | 7z t $_.FullName *>$null; if ($LASTEXITCODE -ge 1) { Write-Host "$_ ! password protected zip archive"} }
$LASTEXITCODE
if ($LASTEXITCODE -ge 1) {
    Exit 1
} 

find corrupt data in fedora objectStore

Get-ChildItem -Path "\\gds-ms-vbas025.media.int\Archive_Fedora\fedora-data\objectStore" -File -Recurse |
Foreach-Object {
	$fullname = $_.FullName
	$lastmod = $_.LastWriteTime
	try { 
	    $content = Get-Content $fullname -ErrorAction Stop
	}
	catch { 
	    Add-Content -Path C:\docuteam\apps\corrupt-fedora-data.txt -Value $lastmod" - "$fullname
	}
}

file convert to utf8

(Get-Content -path static-fileformat-triples.nt) | Set-Content -Encoding UTF8NoBOM -Path static-fileformat-triples.nt

MD5 checksum of a string

$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = New-Object -TypeName System.Text.UTF8Encoding
$String = "Hello, world!"
$Hash = ([System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($String)))).replace("-","").ToLower()

MD5 checksum of a file

Get-FileHash <filepath> -Algorithm MD5