Ga naar inhoud

Scripting — PowerShell Cheatsheet

PowerShell-automatisatie en projectaanpak — 2024–2025


Inhoudstafel


PowerShell-model

Get-Command *Service*
Get-Help Get-Service -Full
Get-Help Get-Service -Examples
Get-Member

Cmdlets volgen Verb-Noun; gebruik goedgekeurde werkwoorden (Get-Verb). PowerShell geeft objecten door, geen opgemaakte tekst. Aliases zijn handig interactief maar onduidelijk in scripts.

Operator Betekenis
-eq, -ne gelijk, ongelijk
-lt, -le, -gt, -ge vergelijken
-like, -match wildcard, regex
-contains, -in collectie bevat waarde
-and, -or, -not logica
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

Deze instellingen maken verborgen fouten sneller zichtbaar, maar test bestaande scripts omdat non-terminating errors dan terminating kunnen worden.


Objecten en pipeline

Get-Service |
    Where-Object Status -eq 'Running' |
    Sort-Object DisplayName |
    Select-Object Name, DisplayName, Status
Get-Process |
    Select-Object Name, Id, @{Name='MemoryMB'; Expression={ [math]::Round($_.WorkingSet64 / 1MB, 2) }}
Cmdlet Taak
Where-Object filteren
Select-Object properties kiezen/berekenen
Sort-Object sorteren
Group-Object groeperen
Measure-Object tellen/som/gemiddelde
ForEach-Object elk pipeline-object verwerken

Format aan het einde

Format-Table en Format-List maken opmaakobjecten. Gebruik ze alleen als laatste stap voor schermuitvoer, nooit vóór export of verdere verwerking.

$services = Get-Service             # data
$services | Export-Csv services.csv -NoTypeInformation
$services | Format-Table            # presentatie

Variabelen en collecties

[string]$Name = 'Ada'
[int]$Count = 3
[datetime]$Today = Get-Date
[bool]$Enabled = $true
$null
$array = @('a', 'b', 'c')
$array[0]
$array[-1]

$list = [System.Collections.Generic.List[string]]::new()
$list.Add('item')

$settings = @{
    Domain = 'lab.local'
    Prefix = 'LAB'
}
$settings.Domain

Gebruik [pscustomobject] voor records:

$result = [pscustomobject]@{
    Computer = $env:COMPUTERNAME
    Success  = $true
    Time     = Get-Date
}

Variabelen in dubbele quotes worden geëxpandeerd; enkele quotes zijn letterlijk. Gebruik $($object.Property) voor expressies in strings.


Selectie en herhaling

if ($FreePercent -lt 10) {
    'Critical'
} elseif ($FreePercent -lt 20) {
    'Warning'
} else {
    'OK'
}
switch -Regex ($line) {
    '^ERROR' { 'Foutregel' }
    '^WARN'  { 'Waarschuwing' }
    default  { 'Andere regel' }
}
foreach ($user in $users) { $user.Name }
for ($i = 0; $i -lt $items.Count; $i++) { $items[$i] }
while ($service.Status -ne 'Running') { $service.Refresh() }
do { $answer = Read-Host 'ja/nee' } until ($answer -in 'ja','nee')

Vermijd oneindige loops: voorzie timeout, maximum pogingen of expliciete stopconditie.


Functies en scripts

function New-ProjectFolder {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [string]$Path,

        [switch]$Force
    )

    process {
        if ($PSCmdlet.ShouldProcess($Path, 'Create directory')) {
            New-Item -ItemType Directory -Path $Path -Force:$Force
        }
    }
}

Advanced functions ondersteunen common parameters zoals -Verbose, -ErrorAction en bij SupportsShouldProcess ook -WhatIf/-Confirm.

Scriptparameters

[CmdletBinding()]
param(
    [Parameter(Mandatory)]
    [ValidateScript({ Test-Path $_ -PathType Leaf })]
    [string]$ConfigPath
)

Gebruik return spaarzaam: alle niet-opgevangen output komt in de pipeline. Statusmeldingen horen bij Write-Verbose; waarschuwingen bij Write-Warning; objectresultaten op de success stream.

Scope en modules

  • Vermijd globale variabelen.
  • Geef data via parameters en returnobjecten door.
  • Zet herbruikbare functies in een .psm1 en exporteer doelbewust.
  • Gebruik een .psd1-manifest voor metadata en exports.

Foutafhandeling en logging

try {
    $content = Get-Content -LiteralPath $Path -ErrorAction Stop
} catch [System.IO.FileNotFoundException] {
    Write-Error "Bestand niet gevonden: $Path"
} catch {
    Write-Error "Mislukt: $($_.Exception.Message)"
    throw
} finally {
    # cleanup die altijd moet gebeuren
}

try/catch vangt terminating errors. Voeg -ErrorAction Stop toe wanneer een cmdlet anders alleen een non-terminating error schrijft.

function Write-Log {
    param([string]$Message, [ValidateSet('INFO','WARN','ERROR')]$Level = 'INFO')
    $entry = '{0:o} [{1}] {2}' -f (Get-Date), $Level, $Message
    Add-Content -LiteralPath $script:LogPath -Value $entry
}

Log actie, doelobject, resultaat en bruikbare foutcontext; log nooit wachtwoorden of secrets.


Bestanden en dataformaten

Get-Content -LiteralPath file.txt
Set-Content -LiteralPath file.txt -Value $data -Encoding utf8
Add-Content -LiteralPath file.txt -Value $line
Get-ChildItem -LiteralPath $root -Recurse -File
Test-Path -LiteralPath $path

Gebruik -LiteralPath voor paden die [ ] of wildcards kunnen bevatten.

CSV

$users = Import-Csv users.csv
$users | Export-Csv output.csv -NoTypeInformation -Encoding utf8

CSV levert strings: cast numerieke, datum- en booleanvelden expliciet.

JSON

$config = Get-Content config.json -Raw | ConvertFrom-Json
$object | ConvertTo-Json -Depth 10 | Set-Content result.json -Encoding utf8

XML

[xml]$xml = Get-Content config.xml -Raw
$xml.Settings.Domain.Name

Hashtable/config combineren

Valideer verplichte velden vóór je wijzigingen uitvoert. Normaliseer data naar één intern objectmodel, ook als input uit CSV, JSON en XML komt.


Windows- en AD-automatisatie

Get-LocalUser
New-LocalUser -Name 'operator' -Password $securePassword
Add-LocalGroupMember -Group 'Remote Desktop Users' -Member 'operator'

Get-SmbShare
New-SmbShare -Name 'Data' -Path 'D:\Data' -ChangeAccess 'LAB\Data_RW'
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase 'OU=Users,DC=lab,DC=local'
New-ADOrganizationalUnit -Name 'Sales' -Path 'DC=lab,DC=local'
New-ADGroup -Name 'GG_Sales' -GroupScope Global -GroupCategory Security -Path $ou
Add-ADGroupMember -Identity 'GG_Sales' -Members $user

Idempotentie

Een script moet veilig opnieuw uitvoerbaar zijn:

if (-not (Get-ADOrganizationalUnit -LDAPFilter '(ou=Sales)' -SearchBase $base -ErrorAction SilentlyContinue)) {
    New-ADOrganizationalUnit -Name 'Sales' -Path $base
}

Controleer bestaande toestand, wijzig alleen verschil en rapporteer wat gebeurde. Gebruik -WhatIf bij risicovolle beheeracties.


Robuuste projectstructuur

project/
├── Invoke-Deployment.ps1
├── Config/
│   ├── Domain.Settings.xml
│   └── users.json
├── Data/
│   ├── ous.csv
│   ├── securitygroups.csv
│   └── shares.csv
├── Modules/
│   └── ProjectTools.psm1
└── Logs/

Aanbevolen fasen:

  1. parameters en paden bepalen;
  2. configuratie/data inlezen;
  3. schema, verplichte waarden en referenties valideren;
  4. plan tonen (-WhatIf);
  5. afhankelijkheden in volgorde uitvoeren: OUs → groups → users → memberships → folders → ACLs → shares;
  6. per stap fouten afhandelen en loggen;
  7. eindtoestand verifiëren en samenvatten.

Geen plaintextwachtwoorden

Gebruik SecureString, een secret store/vault of veilige interactieve invoer. Zet credentials niet in broncode, CSV, JSON of logs.