NEUERUNGEN IN POWERSHELL 7
Listing 1: Konfigurationsdatei
"C:\Program Files\PowerShell\7\
powershell.config.json"
{
"Microsoft.PowerShell:ExecutionPolicy":
"Unrestricted",
"WindowsPowerShellCompatibilityModuleDenyList": [
"PSScheduledJob",
"BestPractices",
"UpdateServices"
],
"DisableImplicitWinCompat": true //
disable WinPSCompatSessions
}
WINDOWS PRESENTATION FOUNDATION
Listing 1: XAML zur Beispiel-Schnittstelle
Listing 2: Steuerelement anlegen
Listing 3: Rückgabe eines Steuerelements
$window = [Windows.Mark-up.XamlReader]::
Load($reader)
$btnFauch = $window.FindName("CmdFauch")
$txtVictim = $window.FindName
("TxtVictimName")
$btnFauch.Add_Click({
$txtVictim.Text = "Fauch!"
})
$window.ShowDialog()
Listing 4: Einbau eines Label-Steuerelements
Für seine eigentliche Inbetriebnahme ist ein
weiterer Eventhandler erforderlich:
$btnWefz = $window.FindName("CmdWefz")
$txtAusgabe = $window.FindName("TxtAusgabe")
$btnWefz.Add_Click({
$angabe = $txtVictim.Text +
"wird angewefzt!"
$txtAusgabe.Text = $angabe
}
Listing 5: Mehrere Radiobuttons aktivieren
[…]
Listing 6: Nach einem Klick Fenster schließen
$btnZenz = $window.FindName("CmdZenz")
$btnZenz.Add_Click({
$chkNerv1= $window.FindName("ChkNerv1")
$chkNerv2 = $window.FindName("ChkNerv2")
If($chkNerv1.IsChecked){
If($chkNerv2.IsChecked){
$window.DialogResult=$true
}
}
})
Listing 7: Endlosschleife einbauen
$btnZenz = $window.FindName("CmdZenz")
$btnZenz.Add_Click({
$chkNerv1= $window.FindName("ChkNerv1")
$chkNerv2 = $window.FindName("ChkNerv2")
If($chkNerv1.IsChecked){
If($chkNerv2.IsChecked){
for ($i = 1; $i -le 10; $i++) {
Start-Sleep -Seconds 2
Write-Host "Ping"
$txtAusgabe.Text =
$txtAusgabe.Text + " XXX "
} }
}
}
TUIS FÜR SKRIPTE
Listing 1: Widgets verbinden
$Window = [Terminal.Gui.Window]::new()
$Window.Title = "Das musikalische Fenster!"
$Button = [Terminal.Gui.Button]::new()
$Button.Text = "Fauchen"
$Button.X = 5
$Button.Y = 5
$Window.Add($Button)
$Button2 = [Terminal.Gui.Button]::new()
$Button2.Text = "Quieken"
$Button2.X = [Terminal.Gui.Pos]::
Right($Button)
$Button2.Y = 5
$Window.Add($Button2)
$Button3 = [Terminal.Gui.Button]::new()
$Button3.Text = "Wefzen"
$Button3.X = [Terminal.Gui.Pos]::
Right($Button2)
$Button3.Y = 5
$Window.Add($Button3)
Listing 2: Platzieren von Funktionen
$Button.add_Clicked({ hissAtSomeone })
$Window.Add($Button)
$Button2.add_Clicked({ squeakAtSomeone })
$Window.Add($Button2)
$Button3.add_Clicked({ wefzAtSomeone })
$Window.Add($Button3)
PARALLELISIERUNG VON SKRIPTEN
Listing 1: Thread-Pool
$Runspaces = foreach ($Item in $ItemList) {
$PSInstance = [powershell]::Create().AddScript({
param($Item)
Start-Sleep -Seconds 10
"Statusmeldung des Items"
$Item
}).AddParameter('Item', $Item)
$PSInstance.RunspacePool = $RunspacePool
New-Object psobject -Property @{
Instance = $PSInstance
Result = $PSInstance.BeginInvoke()
}
}
Listing 2: StringBuilder
$musikvariable =
[System.Text.StringBuilder]::new()
1..20 | ForEach-Object -Parallel {
$localMusic = $using:musikvariable
$localMusic = $localMusic.ToString()
$waitTime = Get-Random -Maximum 10
Start-Sleep -Seconds $waitTime
$localMusic = $localMusic + " laestig "
$sb = $using:musikvariable
$ruhe = $sb.Clear()
$ruhe = $sb.Append($localMusic)
} -ThrottleLimit 20
$musikvariable.ToString()
WINDOWS PACKAGE MANAGER
Listing 1: WinGet Argument Completer
#Quelle: https://github.com/microsoft/
winget-cli/blob/master/doc/Completion.md
Register-ArgumentCompleter -Native -CommandName winget -ScriptBlock {
param($wordToComplete, $commandAst,
$cursorPosition)
[Console]::InputEncoding =
[Console]::OutputEncoding =
$OutputEncoding =
[System.Text.Utf8Encoding]::new()
$Local:word = $wordToComplete.
Replace('"', '""')
$Local:ast =
$commandAst.ToString().
Replace('"', '""') winget complete
--word="$Local:word" --commandline
"$Local:ast" --position
$cursorPosition | ForEach-Object {
[System.Management.Automation.
CompletionResult]::new($_, $_,
'ParameterValue', $_)
}
}
Listing 2: YAML-Manifest für Brave (Auszug)
#Quelle: https://github.com/microsoft/wingetpkgs/blob/master/manifests/b/Brave/Brave/1
20.1.61.114/Brave.Brave.installer.yaml
Installers:
[..]
- Architecture: x64
Scope: user
InstallerUrl: https://updates-cdn.bravesoftware.com/build/Brave-Release/x64-
rel/win/120.1.61.114/brave_installerx64.exe
InstallerSha256:
C0233BC92B512126CF985DDA4E7BBC552C87CA80F4
FA344E8474A2B8EF3D2DE5
InstallerSwitches:
Custom: --do-not-launch-chrome
ProductCode: BraveSoftware Brave-Browser
- Architecture: x64
Scope: machine
InstallerUrl: https://updates-cdn.bravesoftware.com/build/Brave-Release/x64-
rel/win/120.1.61.114/brave_installerx64.exe
InstallerSha256:
C0233BC92B512126CF985DDA4E7BBC552C87CA80F4
FA344E8474A2B8EF3D2DE5
InstallerSwitches:
Custom: --do-not-launch-chrome
--system-level
ProductCode: BraveSoftware Brave-Browser
Listing 3: Konfigurationsdatei settings.json
#Quelle: https://github.com/microsoft/
winget-cli/blob/master/doc/Settings.md
{
"$schema": "https://aka.ms/wingetsettings.schema.json",
"installBehavior": {
"preferences": {
"scope": "user"
}
}
}
Listing 4: WinGet-Cmdlets
## Installieren
Get-WinGetPackage -Moniker vscode
Find-WinGetPackage -Moniker vscode
Install-WinGetPackage -Id Microsoft.VisualStudioCode.Insiders -Scope System
## Installation mittels Pipelining
Find-WinGetPackage -Name 'Mozilla'
-source msstore | Install-WinGetPackage
Find-WinGetPackage -Name 'Mozilla'
-source winget | Install-WinGetPackage
-Scope System
Listing 5: Fehlerhafte Cmdlets
## Cmdlets mit Pluralformen, die Hash-Tabellen ausgeben anstelle von PowerShell-Objekten
Get-WinGetSettings
Get-WinGetUserSettings
## Eine spezifische Einstellung abfragen
(Get-WinGetSettings).adminSettings.InstallerHashOverride
(Get-WinGetUserSettings).visual.progressBar
## Eine spezifische Einstellung aktivieren/deaktivieren
Enable-WinGetSetting -Name InstallerHashOverride
Disable-WinGetSetting -Name InstallerHashOverride
Set-WinGetUserSettings -UserSettings @{
'installBehavior' = @{preferences = @{scope='machine'}}
'visual' = @{progressBar = 'rainbow'}
'telemtry' = @{disable = 'true'}
}
Listing 6: TaskbarAlignment.dsc.yaml
properties:
assertions:
- resource: Microsoft.Windows.
Developer/OSVersion
directives:
description: Verifiy minimum OS
version
allowPrerelease: true
settings:
MinVersion: '10.0.22000' ## Windows
11 (21H2)
resources:
- resource: Microsoft.Windows.Developer/
TaskBarAlignment
directives:
description: Set taskbar alignment
to left
allowPrerelease: true
settings:
Alignment: Left
configurationVersion: 0.1.0
KLASSEN VERWENDEN
Listing 1: Get-LocalUser
$localusers = Get-LocalUser
$localusers | Add-Member -MemberType NoteProperty 'Computername' -Value $env:COMPUTERNAME
$localusers | Select-Object -Property 'Name','Enabled','Computername'
## Ausgabe:
Name Enabled Computername
---- ------- ------------
Administrator True pc1
Jen True pc1
DefaultAccount False pc1
Guest False pc1
WDAGUtilityAccount False pc1
$localusers | Get-Member
## Ausgabe:
TypeName: Microsoft.PowerShell.Commands.LocalUser
Name MemberType Definition
---- ---------- ----------
Clone Method Microsoft.PowerShell.Commands.LocalUser Clone()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Computername NoteProperty string Computername=pc1
AccountExpires Property System.Nullable[datetime] AccountExpires {get;set;}
Description Property string Description {get;set;}
Enabled Property bool Enabled {get;set;}
FullName Property string FullName {get;set;}
LastLogon Property System.Nullable[datetime] LastLogon {get;set;}
Name Property string Name {get;set;}
ObjectClass Property string ObjectClass {get;set;}
PasswordChangeableDate Property System.Nullable[datetime] PasswordChangeableDate {get;set;}
PasswordExpires Property System.Nullable[datetime] PasswordExpires {get;set;}
PasswordLastSet Property System.Nullable[datetime] PasswordLastSet {get;set;}
PasswordRequired Property bool PasswordRequired {get;set;}
Listing 2: Splatting
$addMemberSplat = @{
MemberType = 'ScriptProperty'
Name = 'LastLogonElapsedDays'
Value = {[int] ((Get-Date) - $this.lastlogon).TotalDays}
}
## Main
$localusers = Get-LocalUser
$localusers | Add-Member @addMemberSplat
$localusers | Select-Object -Property Name,Enabled,LastLogonElapsedDays
## Ausgabe:
Name Enabled LastLogonElapsedDays
---- ------- --------------------
Administrator True 2
Jen True 7
DefaultAccount False
Guest False
WDAGUtilityAccount False
Listing 2: Mitarbeiterkonten
#Requires -Modules
'Microsoft.PowerShell.LocalAccounts','ActiveDirectory',
'Microsoft.Graph'
#Requires -Version 5.1
class employee {
[string] $givenName
[string] $surName
## Used for samAccountName, mailNickName et cetera
[string] $userName
[string] $city
[datetime] $employedSince
[string] $displayName
## AzureAD/EntraID domain name (typically the email suffix)
[string] $entraIDDomain
## Hidden properties will not be displayed in default output
[securestring]hidden $password
## Method A: create local user account
[void] createLocalUser() {
if ($this.username -and $this.password) {
$newLocalUserSplat = @{
Name = $this.userName
FullName = "$($this.givenName) $($this.surname)"
Password = $this.password
}
New-LocalUser @newLocalUserSplat
}
}
## Method B: create AD user account
[void] createADUser() {
if ($this.username -and $this.password ) {
$newADUserSplat = @{
Name = "$($this.givenName)
$($this.surname)"
GivenName = $this.givenName
Surname = $this.surName
SamAccountName = $this.userName
AccountPassword = $this.password
ChangePasswordAtLogon = $true
Enabled = $false
}
New-ADUser @newADUserSplat
}
}
## Method C: create EntraID user account (Microsoft.Graph)
[void] createEntraIDUser() {
if ($this.username -and $this.password ) {
$pwProfile = @{
'Password' = $this.showPlainTextPassword()
'ForceChangePasswordNextSignIn' = $true
}
if ($pwProfile) {
$newMGUserSplat = @{
DisplayName = "$($this.givenName)
$($this.surname)"
UserPrincipalName = $this.userName + '@' +
$this.entraIDDomain
MailNickName = $this.userName
PasswordProfile = $pwProfile
AccountEnabled = $true
GivenName = $this.givenName
Surname = $this.surname
}
New-MGUser @newMGUserSplat
}
}
}
## Method D: convert PW to plain text
[string] showPlainTextPassword() {
if ($this.password) {
$netCredential = [System.Net.NetworkCredential]::new($null,
$this.password)
return $netCredential.Password
}
else {
return $null
}
}
## Constructor 1 (testing)
employee() {
}
## Constructor 2 (provide mandatory properties)
employee([string] $givenName, [string] $surname, [string]
$entraIDDomain, [securestring] $password) {
$this.givenName = $givenName
$this.surName = $surname
$this.password = $password
$this.entraIDDomain = $entraIDDomain
$this.userName = $this.surName.Substring(0, 4) +
$this.givenName.Substring(0, 1)
$this.displayName = "$($this.givenName) $($this.surname)"
}
}
class apprentice:employee {
[string] $mentor
[string] $college
[DateTime] $educationStart
[DateTime] $educationEnd
## Constructor 1
apprentice() {
}
## Constructor 2
apprentice([string] $givenName, [string] $surname, [string]
$entraIDDomain, [securestring] $password, [string] $mentor) {
$this.givenName = $givenName
$this.surName = $surname
$this.password = $password
$this.entraIDDomain = $entraIDDomain
$this.mentor = $mentor
$this.username = $this.surName.Substring(0, 4) +
$this.givenName.Substring(0, 1)
$this.displayName = "$($this.givenName) $($this.surname)"
}
}
## Testing: stripped-down object
[employee]::new()
## Create new employee object
$password = ConvertTo-SecureString -AsPlainText -Force -String 'Pa$$w0rd'
$newEmployee = [employee]::new('Jen', 'Barber', 'reynholm.co.uk',
$password)
$newEmployee.showPlainTextPassword()
## Create new apprentice object
$newApprentice = [apprentice]::new('Maurice', 'Moss', 'reynholm.co.uk',
$password, 'BarbJ')
$newApprentice.showPlainTextPassword()
## Create new accounts (employee)
$newEmployee.createLocalUser() ## New local user
$newEmployee.createADUser() ## New AD user
$newEmployee.createEntraIDUser() ## New EntraID user
## Create a new apprentice object with optional properties
$newApprentice.city = 'London'
$newApprentice.employedSince = $newApprentice.educationStart = Get-Date
-Date '2006-02-03'
$newApprentice.educationEnd = $newApprentice.educationStart.AddYears(3)
$newApprentice.college = "St Catharine's College"
## Create new accounts (Apprentice)
$newApprentice.createLocalUser()
$newApprentice.createADUser()
$newApprentice.createEntraIDUser()