Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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. Nichts ist beängstigender, als einen Befehl zum ersten Mal auszuführen, von dem man weiß, dass er gefährlich sein kann. Die Option, ihn mit -WhatIf auszuführen, kann da einen großen Unterschied ausmachen.
GemeinsameParameter
Bevor wir uns mit der Implementierung dieser Allgemeine Parameter befassen, möchte ich kurz darauf eingehen, wie diese verwendet werden.
Verwendung von -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 Sie -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. Die Hilfeanzeige beschreibt jede dieser Optionen wie folgt.
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
Sehen wir uns einen kurzen Moment an, wie Sie einen Wert an einen [switch] Parameter übergeben können. 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 für alle Parameter verwendet werden kann, sie wird jedoch hauptsächlich für [switch] Parameter verwendet. Sie geben einen Doppelpunkt an, um einen Wert dem Parameter zuzuweisen.
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, gibt es einen weiteren Artikel, der alles, was Sie schon immer über Hashtabellen wissen wollten, behandelt.
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 etwas nicht funktioniert, und ich werde es sehr deutlich machen, wenn ich andere Befehle aufrufe. 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 $true ausgewählt hat, wird Y 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"):
Eine tolle Funktion von $PSCmdlet.ShouldProcess ist, dass sie doppelt so gut als ausführliche Ausgabe funktioniert. 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 einige verschiedene Überladungen für $PSCmdlet.ShouldProcess mit unterschiedlichen Parametern zum Anpassen der Nachrichtenverarbeitung. 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 eine vierte Überladung, die fortgeschrittener 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.
Wo man es platzieren sollte
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 Anruf wird also innerhalb der foreach Schleife platziert.
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 ein Logikstück habe, das in Pester schwer zu simulieren ist, kann ich es oft in ShouldProcess umschließen und mit -WhatIf in meinen Tests aufrufen. Es ist immer noch besser, einen Teil Ihres Codes zu testen als gar keinen.
$WhatIfPreference
Unsere erste Präferenzvariable 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"
}
}
Dieser Aufruf von Test-ShouldProcess führt die -Confirm-Aktion aufgrund der High-Auswirkung 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.
HighMediumLowNone
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 rufen, wird der Wert von $ConfirmPreference innerhalb des Gültigkeitsbereichs der Funktion auf Low festgelegt.
Unterdrücken von geschachtelten Bestätigungsaufforderungen
$ConfirmPreference kann von den Funktionen übernommen werden, die Sie aufrufen. 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, weil bei jeder Ausführung eine Eingabeaufforderung erfolgt.
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 SupportsShouldProcess als CmdletBinding 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
OPERATION
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'.
Wenn Sie sich an den Abschnitt ConfirmImpact erinnern, müssen sie ihn tatsächlich so aufrufen:
Test-ShouldProcess -Confirm:$false
Nicht jeder erkennt, dass sie das tun müssen, und -Force nicht ShouldContinue unterdrücken kann.
Daher sollten wir -Force für die Zuverlässigkeit unserer Benutzer 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 keinen Test für den $Force-Wert in der if-Anweisung mit dem ShouldProcess 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"
}
}
Indem man das $Force links vom -or-Operator platziert, wird es 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
Der Einsatz von -WhatIf und -Confirm sollte auf alles innerhalb Ihrer Funktionen sowie auf alles, was sie aufrufen, angewandt 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 aufrufen.
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 halte dies persönlich für sehr gefährlich, weil dadurch Szenarien entstehen, bei denen Sie -WhatIf-Unterstützung zu mehreren Modulen hinzufügen, die isoliert korrekt funktionieren, aber versagen, wenn sie sich gegenseitig aufrufen.
Wir haben ein GitHub-RFC in Arbeit, 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).
Zum 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.