PowerShell Scripte mit WhatIf

Manchmal ist es sinnvoll den Aufruf eines eigenen PowerShell Scripts nur zu simulieren. Statt die Aktionen wirklich auszuführen möchte man lediglich sehen was passieren würde. Viele Cmdlets unterstützen den Parameter -WhatIf. Benutzt man diesen z.B. beim Anlegen eines Verzeichnis wird dieses nicht erstellt, sondern lediglich die im Beispiel angezeigte Meldung ausgegeben:

1
New-Item -ItemType Directory -Name "test" -Path "c:\temp" -WhatIf
PS C:\> New-Item -ItemType Directory -Name "test" -Path "c:\temp" -WhatIf
What if: Performing the operation "Create Directory" on target "Destination: C:\temp\test".

In einem eigenen Script kann die Option -WhatIf durch CmdletBinding verwendet werden.

1
2
3
4
5
6
[CmdletBinding(SupportsShouldProcess=$True)]
Param()

Get-ChildItem -Directory "c:\temp"
Out-File -FilePath "c:\temp\Test-WhatIf.log" -InputObject "Text" -Encoding ASCII
New-Item -ItemType Directory -Name "test" -Path "c:\temp"

Das Script lautet Test-WhatIf.ps1. Gibt man beim Aufruf den Parameter WhatIf an, werden alle Cmdlets die WhatIf unterstützen ausgeführt als wäre der Parameter im Code selbst angegeben. Das Cmdlet Get-ChildItem z.B. unterstützt WhatIf nicht, der Inhalt wird also aufgelistet.

PS C:\> ./Test-WhatIf.ps1 -WhatIf

    Directory: C:\temp

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        19.05.2016     14:58            directory1
d----        11.07.2016     10:22            directory2
d----        06.07.2016     15:56            directory3
d----        19.05.2016     15:12            directory4
What if: Performing the operation "Output to File" on target "c:\temp\Test-WhatIf.log".
What if: Performing the operation "Create Directory" on target "Destination: C:\temp\test".

Evtl. möchte man aber auch Teile des Scripts trotzdem ausführen. In diesem Fall kann man -WhatIf manuell auf $False setzen:

1
2
3
4
5
6
[CmdletBinding(SupportsShouldProcess=$True)]
Param()

Get-ChildItem -Directory "c:\temp"
Out-File -FilePath "c:\temp\Test-WhatIf.log" -InputObject "Text" -Encoding ASCII -WhatIf:$False
New-Item -ItemType Directory -Name "test" -Path "c:\temp"

Das Script schreibt den Text in die Datei, erstellt das Verzeichnis aber nicht.

PS C:\> ./Test-WhatIf.ps1 -WhatIf

    Directory: C:\temp

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        19.05.2016     14:58            directory1
d----        11.07.2016     10:22            directory2
d----        06.07.2016     15:56            directory3
d----        19.05.2016     15:12            directory4
What if: Performing the operation "Create Directory" on target "Destination: C:\temp\test".
PS C:\> Get-Content "c:\temp\Test-WhatIf.log"
Text

Ausserdem kann es sinnvoll sein im Script zu unterscheiden, ob es mit -WhatIf augerufen wurde oder nicht. Dafür kann die Variable $WhatIfPreference genutzt werden:

1
2
3
4
5
6
7
8
[CmdletBinding(SupportsShouldProcess=$True)]
Param()

If ($WhatIfPreference) {
    Write-Host "aufgerufen mit WhatIf"
} Else {
    Write-Host "aufgerufen ohne WhatIf"
}
PS C:\> ./Test-WhatIf.ps1 -WhatIf
aufgerufen mit WhatIf

PS C:\> ./Test-WhatIf.ps1
aufgerufen ohne WhatIf