Alles, was Sie schon immer über ShouldProcess wissen wollten
PowerShell-Funktionen verfügen über mehrere Features, die die Interaktion der Benutzer mit ihnen erheblich verbessern.
Ein wichtiges Feature, das oft übersehen wird, ist die Unterstützung von -WhatIf
und -Confirm
– diese lässt sich ganz einfach zu Ihren Funktionen hingefügen. In diesem Artikel möchte ich Ihnen ausführlich erläutern, wie Sie dieses Feature implementieren.
Hinweis
Die Originalversion dieses Artikels erschien ursprünglich in einem Blog von @KevinMarquette. Das PowerShell-Team dankt Kevin Marquette, dass er diesen Inhalt mit uns teilt. Weitere Informationen finden Sie in seinem Blog auf PowerShellExplained.com.
Dies ist ein einfaches Feature, das Sie in Ihren Funktionen aktivieren können, um ein Sicherheitsnetz für die Benutzer bereitzustellen, die es benötigen. Es kann schon sehr beängstigend sein, zum ersten Mal einen Befehl auszuführen, von dem Sie wissen, dass er gefährlich sein kann. Die Option, ihn mit -WhatIf
auszuführen, kann da einen großen Unterschied ausmachen.
CommonParameters
Bevor wir uns mit der Implementierung dieser Allgemeine Parameter befassen, möchte ich kurz darauf eingehen, wie diese verwendet werden.
Verwenden: -WhatIf
Wenn ein Befehl den -WhatIf
-Parameter unterstützt, können Sie sehen, was der Befehl getan hätte, anstatt die Änderungen direkt vorzunehmen. Das ist eine gute Möglichkeit, die Auswirkungen eines Befehls zu testen, vor allem, bevor Sie etwas tun, das zerstörerische Folgen haben könnte.
PS C:\temp> Get-ChildItem
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/19/2021 8:59 AM 0 importantfile.txt
-a---- 4/19/2021 8:58 AM 0 myfile1.txt
-a---- 4/19/2021 8:59 AM 0 myfile2.txt
PS C:\temp> Remove-Item -Path .\myfile1.txt -WhatIf
What if: Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
Wenn der Befehl ShouldProcess
ordnungsgemäß implementiert, sollte er Ihnen alle Änderungen zeigen, die er vorgenommen hätte. Im Folgenden sehen Sie ein Beispiel für die Verwendung eines Platzhalters zum Löschen mehrerer Dateien.
PS C:\temp> Remove-Item -Path * -WhatIf
What if: Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
What if: Performing the operation "Remove File" on target "C:\Temp\myfile2.txt".
What if: Performing the operation "Remove File" on target "C:\Temp\importantfile.txt".
Verwenden: -Confirm
Befehle, die -WhatIf
unterstützen, unterstützen auch -Confirm
. Dadurch haben Sie die Möglichkeit, eine Aktion zu bestätigen, bevor Sie sie ausführen.
PS C:\temp> Remove-Item .\myfile1.txt -Confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
In diesem Fall haben Sie mehrere Optionen, mit denen Sie das Skript fortsetzen, eine Änderung überspringen oder das Skript anhalten können. In der Hilfeanzeige werden die einzelnen Optionen beschrieben.
Y - Continue with only the next step of the operation.
A - Continue with all the steps of the operation.
N - Skip this operation and proceed with the next operation.
L - Skip this operation and all subsequent operations.
S - Pause the current pipeline and return to the command prompt. Type "exit" to resume the pipeline.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
Lokalisierung
Diese Eingabeaufforderung ist in PowerShell lokalisiert, sodass sich die Sprache basierend auf der Sprache Ihres Betriebssystems ändert. Dies ist ein weiterer Aspekt, den PowerShell für Sie übernimmt.
Switch-Parameter
Schauen wir uns kurz an, wie Sie einen Wert an einen Switch-Parameter übergeben. Ich spreche diesen Aspekt hauptsächlich deswegen an, weil es häufig vorkommen wird, dass Sie Parameterwerte an die Funktionen übergeben möchten, die Sie aufrufen.
Der erste Ansatz ist eine spezifische Parametersyntax, die sich zwar für alle Parameter eignet, aber meistens für Switch-Parameter eingesetzt wird. Um einen Wert an den Parameter anzufügen, geben Sie einen Doppelpunkt an.
Remove-Item -Path:* -WhatIf:$true
Dasselbe können Sie mit einer Variablen machen.
$DoWhatIf = $true
Remove-Item -Path * -WhatIf:$DoWhatIf
Der zweite Ansatz besteht darin, eine Hashtabelle zum Splatten des Werts zu verwenden.
$RemoveSplat = @{
Path = '*'
WhatIf = $true
}
Remove-Item @RemoveSplat
Wenn Sie noch nicht mit Hashtabellen oder dem Splatting vertraut sind, lesen Sie den Artikel Alles, was Sie schon immer über Hashtabellen wissen wollten.
SupportsShouldProcess
Der erste Schritt beim Aktivieren der Unterstützung für -WhatIf
und -Confirm
besteht darin, SupportsShouldProcess
in der CmdletBinding
der Funktion anzugeben.
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
Remove-Item .\myfile1.txt
}
Wenn wir SupportsShouldProcess
auf diese Weise angeben, können wir die Funktion mit -WhatIf
(oder -Confirm
) aufrufen.
PS> Test-ShouldProcess -WhatIf
What if: Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
Beachten Sie, dass ich keinen Parameter namens -WhatIf
erstellt habe. Durch die Angabe von SupportsShouldProcess
wird dieser automatisch für uns erstellt. Wenn wir den -WhatIf
-Parameter in Test-ShouldProcess
angeben, führen einige Funktionen, die wir aufrufen, auch eine -WhatIf
-Verarbeitung aus.
Hinweis
Wenn Sie SupportsShouldProcess
verwenden, fügt PowerShell die $WhatIf
-Variable nicht zur Funktion hinzu. Sie müssen den Wert von $WhatIf
nicht überprüfen, da die ShouldProcess()
-Methode dies für Sie übernimmt.
Vertrauen ist gut – Kontrolle ist besser
Hier lauert eine gewisse Gefahr, wenn Sie blind darauf vertrauen, dass jeder Befehl, der aufgerufen wird, -WhatIf
-Werte erbt. Bei den weiteren Beispielen gehe ich davon aus, dass dies nicht funktioniert, und werde bei Aufrufen anderer Befehle sehr explizit sein. Ich empfehle Ihnen, genauso vorzugehen.
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
Remove-Item .\myfile1.txt -WhatIf:$WhatIfPreference
}
Ich werde auf die Besonderheiten später noch einmal zurückkommen, wenn Sie alle Puzzleteile kennen.
$PSCmdlet.ShouldProcess
Zum Implementieren von SupportsShouldProcess
benötigen Sie die Methode $PSCmdlet.ShouldProcess
. Sie rufen $PSCmdlet.ShouldProcess(...)
auf, um festzustellen, ob Logik verarbeitet werden muss – um den Rest kümmert sich PowerShell. Beginnen wir mit einem Beispiel:
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
$file = Get-ChildItem './myfile1.txt'
if($PSCmdlet.ShouldProcess($file.Name)){
$file.Delete()
}
}
Der Aufruf von $PSCmdlet.ShouldProcess($file.name)
überprüft, ob der Parameter -WhatIf
(und der Parameter -Confirm
) vorhanden ist, und verarbeitet ihn dann entsprechend. Durch -WhatIf
gibt ShouldProcess
eine Beschreibung der Änderung aus und gibt $false
zurück:
PS> Test-ShouldProcess -WhatIf
What if: Performing the operation "Test-ShouldProcess" on target "myfile1.txt".
Ein Aufruf mit -Confirm
hält das Skript an und fordert den Benutzer zum Fortfahren auf. Wenn der Benutzer Y
ausgewählt hat, wird $true
zurückgegeben.
PS> Test-ShouldProcess -Confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Test-ShouldProcess" on target "myfile1.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
Ein tolles Feature von $PSCmdlet.ShouldProcess
ist, dass es auch eine ausführliche Ausgabe bietet. Das benötige ich beim Implementieren von ShouldProcess
häufig.
PS> Test-ShouldProcess -Verbose
VERBOSE: Performing the operation "Test-ShouldProcess" on target "myfile1.txt".
Überladungen
Es gibt verschiedene Überladungen für $PSCmdlet.ShouldProcess
mit unterschiedlichen Parametern zum Anpassen des Messaging. Die erste findet sich bereits im Beispiel oben. Sehen wir uns das einmal genauer an.
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
if($PSCmdlet.ShouldProcess('TARGET')){
# ...
}
}
Die Ausgabe dieses Beispiels enthält sowohl den Funktionsnamen als auch das Ziel (den Wert des Parameters).
What if: Performing the operation "Test-ShouldProcess" on target "TARGET".
Jetzt geben wir einen zweiten Parameter an, da der Vorgang den Vorgangswert statt des Funktionsnamens in der Meldung verwendet.
## $PSCmdlet.ShouldProcess('TARGET','OPERATION')
What if: Performing the operation "OPERATION" on target "TARGET".
Die nächste Option besteht darin, drei Parameter anzugeben, um die Meldung vollständig anzupassen. Wenn drei Parameter verwendet werden, ist der erste die gesamte Meldung. Die nächsten beiden Parameter werden weiterhin in der Meldungsausgabe von -Confirm
verwendet.
## $PSCmdlet.ShouldProcess('MESSAGE','TARGET','OPERATION')
What if: MESSAGE
Kurze Parameterreferenz
Wenn Sie diesen Artikel nur lesen, um herauszufinden, welche Parameter Sie verwenden sollten, finden Sie hier eine kurze Referenz, die zeigt, wie die Parameter die Meldung in den verschiedenen -WhatIf
-Szenarien verändern.
## $PSCmdlet.ShouldProcess('TARGET')
What if: Performing the operation "FUNCTION_NAME" on target "TARGET".
## $PSCmdlet.ShouldProcess('TARGET','OPERATION')
What if: Performing the operation "OPERATION" on target "TARGET".
## $PSCmdlet.ShouldProcess('MESSAGE','TARGET','OPERATION')
What if: MESSAGE
Ich verwende in der Regel die Variante mit zwei Parametern.
ShouldProcessReason
Es gibt noch eine vierte Überladung, die ausgereifter ist als die anderen. Mit dieser können Sie den Grund für die Ausführung von ShouldProcess
abrufen. Ich führe dies hier nur der Vollständigkeit halber an, weil wir einfach prüfen können, ob $WhatIfPreference
stattdessen $true
ist.
$reason = ''
if($PSCmdlet.ShouldProcess('MESSAGE','TARGET','OPERATION',[ref]$reason)){
Write-Output "Some Action"
}
$reason
Wir müssen die $reason
-Variable als Verweisvariable mit [ref]
an den vierten Parameter übergeben. ShouldProcess
füllt $reason
mit dem Wert None
oder WhatIf
auf. Ich behaupte nicht, dass dies nützlich ist, und es gab für mich bisher auch noch keinen Grund, das so zu verwenden.
Die richtige Position
Mit ShouldProcess
können Sie Ihre Skripts sicherer machen. Verwenden Sie das Feature also dann, wenn Ihre Skripts Änderungen vornehmen. Ich füge den $PSCmdlet.ShouldProcess
-Aufruf gern so nah wie möglich an der Änderung ein.
## general logic and variable work
if ($PSCmdlet.ShouldProcess('TARGET','OPERATION')){
# Change goes here
}
Wenn ich eine Auflistung von Elementen verarbeite, rufe ich das Feature für jedes Element auf. Der Aufruf wird also in der ForEach-Schleife eingefügt.
foreach ($node in $collection){
# general logic and variable work
if ($PSCmdlet.ShouldProcess($node,'OPERATION')){
# Change goes here
}
}
Ich platziere ShouldProcess
um die Änderung, weil ich möchte, dass so viel Code wie möglich ausgeführt wird, wenn -WhatIf
angegeben wird. Die Setup- und Validierungsprozesse sollen nach Möglichkeit ausgeführt werden, damit der Benutzer diese Fehler sehen kann.
Ich verwende das auch gern in meinen Pester-Tests, mit denen meine Projekte validiert werden. Wenn ich mit Logik arbeite, die in Pester schwer zu simulieren ist, kann ich sie häufig in ShouldProcess
umschließen und mit -WhatIf
in meinen Tests aufzurufen. Es ist immer noch besser, einen Teil Ihres Codes zu testen als gar keinen.
$WhatIfPreference
Unsere erste Einstellungsvariable ist $WhatIfPreference
. Diese ist standardmäßig auf $false
festgelegt. Wenn Sie sie auf $true
festlegen, wird die Funktion so ausgeführt, als ob Sie -WhatIf
angegeben haben. Wenn Sie dies in Ihrer Sitzung festlegen, werden alle Befehle mit -WhatIf
ausgeführt.
Wenn Sie eine Funktion mit -WhatIf
aufrufen, wird der Wert von $WhatIfPreference
innerhalb des Gültigkeitsbereichs der Funktion auf $true
festgelegt.
ConfirmImpact
Die meisten meiner Beispiele beziehen sich auf -WhatIf
, sie funktionieren aber auch mit -Confirm
, um dem Benutzer eine Eingabeaufforderung anzuzeigen. Sie können den ConfirmImpact
-Parameter der Funktion auf „High“ festlegen, und der Benutzer wird zu einer Eingabe aufgefordert, so als ob der Aufruf mit -Confirm
erfolgt wäre.
function Test-ShouldProcess {
[CmdletBinding(
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
param()
if ($PSCmdlet.ShouldProcess('TARGET')){
Write-Output "Some Action"
}
}
Da High
festgelegt wurde, führt dieser Aufruf von Test-ShouldProcess
die -Confirm
-Aktion aus.
PS> Test-ShouldProcess
Confirm
Are you sure you want to perform this action?
Performing the operation "Test-ShouldProcess" on target "TARGET".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y
Some Action
Das offensichtliche Problem besteht darin, dass es jetzt schwieriger ist, das Ganze in anderen Skripten zu verwenden, ohne eine Eingabeaufforderung für den Benutzer anzuzeigen. In diesem Fall können wir $false
an -Confirm
übergeben, um die Eingabeaufforderung zu unterdrücken.
PS> Test-ShouldProcess -Confirm:$false
Some Action
In einem späteren Abschnitt werde ich erläutern, wie die -Force
-Unterstützung hinzugefügt wird.
$ConfirmPreference
$ConfirmPreference
ist eine automatische Variable, die steuert, wann ConfirmImpact
Sie zur Bestätigung der Ausführung auffordert. Hier sind die möglichen Werte sowohl für $ConfirmPreference
als auch für ConfirmImpact
.
High
Medium
Low
None
Mit diesen Werten können Sie für jede Funktion unterschiedliche Auswirkungsstufen angeben. Wenn Sie $ConfirmPreference
auf einen höheren Wert als ConfirmImpact
festgelegt haben, werden Sie nicht aufgefordert, die Ausführung zu bestätigen.
Standardmäßig ist $ConfirmPreference
auf High
und ConfirmImpact
auf Medium
festgelegt. Wenn Sie möchten, dass die Funktion dem Benutzer automatisch eine Eingabeaufforderung anzeigt, legen Sie ConfirmImpact
auf High
fest. Legen Sie andernfalls den Wert Medium
fest, wenn die Funktion destruktiv ist, und verwenden Sie Low
, wenn der Befehl in der Produktion immer sicher ausgeführt werden kann. Wenn Sie diesen Wert auf none
festlegen, wird auch dann keine Eingabeaufforderung angezeigt, wenn -Confirm
angegeben wurde (-WhatIf
wird jedoch weiter unterstützt).
Wenn Sie eine Funktion mit -Confirm
aufzurufen, wird der Wert von $ConfirmPreference
innerhalb des Gültigkeitsbereichs der Funktion auf Low
festgelegt.
Unterdrücken von geschachtelten Bestätigungsaufforderungen
$ConfirmPreference
kann von Funktionen übernommen werden, die Sie aufzurufen. Dadurch können Szenarien entstehen, in denen Sie eine Bestätigungsaufforderung hinzufügen und die von Ihnen aufgerufene Funktion den Benutzer ebenfalls auffordert.
Ich gebe in der Regel -Confirm:$false
bei den Befehlen an, die ich aufrufe, wenn ich die Eingabeaufforderung bereits verarbeitet habe.
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
$file = Get-ChildItem './myfile1.txt'
if($PSCmdlet.ShouldProcess($file.Name)){
Remove-Item -Path $file.FullName -Confirm:$false
}
}
Damit kommen wir zurück zu einer früheren Warnung: Es gibt einige feine Unterschiede, wann -WhatIf
nicht an eine Funktion übergeben wird und wann -Confirm
an eine Funktion übergeben wird. Ich werde später noch einmal darauf zurückkommen, versprochen.
$PSCmdlet.ShouldContinue
Wenn Sie mehr Kontrolle benötigen, als ShouldProcess
Ihnen ermöglicht, können Sie die Eingabeaufforderung direkt mit ShouldContinue
auslösen. ShouldContinue
ignoriert $ConfirmPreference
, ConfirmImpact
, -Confirm
, $WhatIfPreference
und -WhatIf
, da bei jeder Ausführung eine Eingabeaufforderung angezeigt wird.
Auf den ersten Blick können ShouldProcess
und ShouldContinue
leicht verwechselt werden. Ich erinnere mich meist deswegen an die Verwendung von ShouldProcess
, weil der Parameter in CmdletBinding
als SupportsShouldProcess
bezeichnet wird.
Sie sollten ShouldProcess
in so ziemlich jedem Szenario verwenden. Aus diesem Grund habe ich diese Methode zuerst erläutert.
Sehen wir uns ShouldContinue
in Aktion an.
function Test-ShouldContinue {
[CmdletBinding()]
param()
if($PSCmdlet.ShouldContinue('TARGET','OPERATION')){
Write-Output "Some Action"
}
}
So erhalten wir eine vereinfachte Eingabeaufforderung mit weniger Optionen.
Test-ShouldContinue
Second
TARGET
[Y] Yes [N] No [S] Suspend [?] Help (default is "Y"):
Das größte Problem bei ShouldContinue
besteht darin, dass die Ausführung durch den Benutzer interaktiv erfolgen muss, weil der Benutzer immer eine Eingabeaufforderung erhält. Sie sollten immer Tools erstellen, die von anderen Skripts verwendet werden können. Zu diesem Zweck implementieren Sie -Force
. Ich komme auf diesen Punkt später noch einmal zurück.
Ja zu allem
Dies wird mit ShouldProcess
automatisch verarbeitet, aber für ShouldContinue
müssen wir etwas mehr Arbeit investieren. Es gibt eine zweite Methodenüberladung, bei der wir per Verweis einige Werte übergeben müssen, um die Logik zu steuern.
function Test-ShouldContinue {
[CmdletBinding()]
param()
$collection = 1..5
$yesToAll = $false
$noToAll = $false
foreach($target in $collection) {
$continue = $PSCmdlet.ShouldContinue(
"TARGET_$target",
'OPERATION',
[ref]$yesToAll,
[ref]$noToAll
)
if ($continue){
Write-Output "Some Action [$target]"
}
}
}
Ich habe eine foreach
-Schleife und eine Auflistung hinzugefügt, um das Ganze in Aktion anzuzeigen. Ich habe den ShouldContinue
-Befehl aus der if
-Anweisung herausgezogen, um die Lesbarkeit zu verbessern. Der Aufruf einer Methode mit vier Parametern wird langsam etwas unschön, aber ich habe versucht, es so übersichtlich wie möglich zu gestalten.
Implementieren: -Force
ShouldProcess
und ShouldContinue
müssen -Force
unterschiedlich implementieren. Der Trick bei diesen Implementierungen ist, dass ShouldProcess
immer ausgeführt werden sollte, ShouldContinue
aber nicht ausgeführt werden sollte, wenn -Force
angegeben ist.
ShouldProcess: -Force
Wenn Sie ConfirmImpact
auf high
festlegen, wird der Benutzer zunächst versuchen, das mit -Force
zu unterdrücken. Das ist sowieso das erste, was ich mache.
Test-ShouldProcess -Force
Error: Test-ShouldProcess: A parameter cannot be found that matches parameter name 'force'.
Wie Sie aus dem Abschnitt ConfirmImpact
wissen, müssen Sie ihn wie folgt bezeichnen:
Test-ShouldProcess -Confirm:$false
Nicht allen ist klar, dass das notwendig ist, und -Force
nicht ShouldContinue
unterdrückt.
Daher sollten wir -Force
für die Benutzerfreundlichkeit implementieren. Schauen wir uns hier dieses vollständige Beispiel an:
function Test-ShouldProcess {
[CmdletBinding(
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
param(
[switch]$Force
)
if ($Force -and -not $PSBoundParameters.ContainsKey('Confirm')) {
$ConfirmPreference = 'None'
}
if ($PSCmdlet.ShouldProcess('TARGET')) {
Write-Output "Some Action"
}
}
Wir fügen unseren Switch -Force
als Parameter hinzu. Der Parameter -Confirm
wird automatisch hinzugefügt, wenn SupportsShouldProcess
in CmdletBinding
verwendet wird. Wenn Sie jedoch SupportsShouldProcess
verwenden, fügt PowerShell die $Confirm
-Variable nicht zur Funktion hinzu. Wenn Sie den Strict-Modus ausführen und versuchen, die $Confirm
-Variable zu verwenden, bevor sie definiert wurde, wird ein Fehler angezeigt. Um den Fehler zu vermeiden, können Sie $PSBoundParameters
verwenden, um zu testen, ob der Parameter vom Benutzer übergeben wurde.
if ($Force -and -not $PSBoundParameters.ContainsKey('Confirm')) {
$ConfirmPreference = 'None'
}
Wenn der Benutzer -Force
angibt, wird $ConfirmPreference
im lokalen Bereich auf None
festgelegt. Wenn der Benutzer auch -Confirm
angibt, berücksichtigt ShoudProcess()
die Werte des -Confirm
-Parameters.
if ($PSCmdlet.ShouldProcess('TARGET')){
Write-Output "Some Action"
}
Wenn sowohl -Force
als auch -WhatIf
angegeben werden, muss -WhatIf
Priorität haben. Dieser Ansatz behält die -WhatIf
-Verarbeitung bei, weil ShouldProcess
immer ausgeführt wird.
Fügen Sie in der if
-Anweisung mit ShouldProcess
keinen Test für den $Force
-Wert hinzu. Es ist ein Antimuster für dieses spezifische Szenario, auch wenn ich Ihnen genau das im nächsten Abschnitt für ShouldContinue
zeige.
ShouldContinue: -Force
Im Folgenden sehen Sie die richtige Vorgehensweise zum Implementieren von -Force
mit ShouldContinue
.
function Test-ShouldContinue {
[CmdletBinding()]
param(
[Switch]$Force
)
if($Force -or $PSCmdlet.ShouldContinue('TARGET','OPERATION')){
Write-Output "Some Action"
}
}
Durch Platzierung links vom -or
-Operator wird $Force
zuerst ausgewertet. Auf diese Weise wird die Ausführung der if
-Anweisung umgangen. Wenn $force
den Wert $true
aufweist, wird ShouldContinue
nicht ausgeführt.
PS> Test-ShouldContinue -Force
Some Action
Wir müssen uns in diesem Szenario nicht um -Confirm
oder -WhatIf
kümmern, da sie von ShouldContinue
nicht unterstützt werden. Aus diesem Grund muss die Verarbeitung anders erfolgen als bei ShouldProcess
.
Bereichsprobleme
Die Verwendung -WhatIf
und -Confirm
sollte für alle Aspekte in Ihren Funktionen sowie für alle Elemente gelten, die von Ihren Funktionen aufgerufen werden. Dazu legen sie im lokalen Gültigkeitsbereich der Funktion $WhatIfPreference
auf $true
oder $ConfirmPreference
auf Low
fest. Wenn Sie eine andere Funktion aufrufen, werden diese Werte in Aufrufen von ShouldProcess
verwendet.
Dies funktioniert in den meisten Fällen ordnungsgemäß. Es funktioniert jedes Mal, wenn Sie ein integriertes Cmdlet oder eine Funktion im selben Gültigkeitsbereich aufrufen. Es funktioniert auch, wenn Sie ein Skript oder eine Funktion in einem Skriptmodul über die Konsole aufzurufen.
Es gibt nur eine Situation, in der das Ganze nicht funktioniert: Wenn ein Skript oder ein Skriptmodul eine Funktion in einem anderen Skriptmodul aufruft. Das klingt vielleicht nicht besonders problematisch, aber die meisten Module, die Sie erstellen oder aus der PSGallery abrufen, sind Skriptmodule.
Das Hauptproblem ist, dass Skriptmodule die Werte für $WhatIfPreference
oder $ConfirmPreference
(und einige andere) nicht erben, wenn sie von Funktionen in anderen Skriptmodulen aufgerufen werden.
Eine allgemeine Regel lässt sich vielleicht so formulieren: Das Ganze funktioniert ordnungsgemäß für binäre Module, aber vertrauen Sie nie darauf, dass es auch für Skriptmodule funktioniert. Wenn Sie sich nicht sicher sind, sollten Sie es entweder testen, oder einfach annehmen, dass es nicht richtig funktioniert.
Ich persönlich sehe ein großes Risiko, weil dadurch Szenarien entstehen, in denen Sie -WhatIf
-Unterstützung zu mehreren Modulen hinzufügen, die isoliert korrekt funktionieren, dies aber nicht mehr tun, wenn sie sich gegenseitig aufrufen.
Wir arbeiten an einem GitHub-RFC, um dieses Problem zu beheben. Weitere Informationen finden Sie unter Propagate execution preferences beyond script module scope (Weitergeben von Ausführungseinstellungen über den Gültigkeitsbereich des Skriptmoduls hinaus).
Abschluss
Ich muss jedes Mal nachschlagen, wie ich ShouldProcess
verwende. Ich habe lange gebraucht, um ShouldProcess
von ShouldContinue
zu unterscheiden. Ich muss fast immer nachschlagen, welche Parameter ich verwenden darf. Machen Sie sich also keine Sorgen, wenn Sie gelegentlich noch etwas verwirrt sind. Sie können diesen Artikel bei Bedarf jederzeit hier lesen. Ich bin mir sicher, dass ich ihn selbst häufig zu Rate ziehen werde.
Wenn Ihnen dieser Beitrag gefallen hat, können Sie mir Ihre Meinung auf Twitter über den untenstehenden Link mitteilen. Ich höre immer gerne von Menschen, für die meine Inhalte hilfreich sind.