Erstellen eines Cmdlet, das das System ändert
Manchmal muss ein Cmdlet den Ausführungsstatus des Systems ändern, nicht nur den Zustand der Windows PowerShell Laufzeit. In diesen Fällen sollte das Cmdlet dem Benutzer die Möglichkeit geben, zu bestätigen, ob die Änderung ausgeführt werden soll.
Um die Bestätigung zu unterstützen, muss ein Cmdlet zwei Dinge ausführen.
Deklarieren Sie, dass das Cmdlet die Bestätigung unterstützt, wenn Sie das Attribut System.Management.Automation.CmdletAttribute angeben, indem Sie das Schlüsselwort SupportsShouldProcess auf
true
festlegen.Rufen Sie System.Management.Automation.Cmdlet.ShouldProcess während der Ausführung des Cmdlets auf (wie im folgenden Beispiel gezeigt).
Durch unterstützungsbestätigung macht ein Cmdlet die Parameter und verfügbar, die von Windows PowerShell bereitgestellt werden, und erfüllt auch die Entwicklungsrichtlinien für Cmdlets (weitere Informationen zu Den Entwicklungsrichtlinien für Cmdlets finden Sie unter Confirm
WhatIf
Cmdlet Development Guidelines.).
Ändern des Systems
Das "Ändern des Systems" bezieht sich auf jedes Cmdlet, das möglicherweise den Zustand des Systems außerhalb der Windows PowerShell. Beispielsweise sind das Beenden eines Prozesses, das Aktivieren oder Deaktivieren eines Benutzerkontos oder das Hinzufügen einer Zeile zu einer Datenbanktabelle alle Änderungen am System, die bestätigt werden sollten.
Im Gegensatz dazu ändern Vorgänge, die Daten lesen oder vorübergehende Verbindungen herstellen, das System nicht und erfordern im Allgemeinen keine Bestätigung. Eine Bestätigung ist auch nicht für Aktionen erforderlich, deren Auswirkung auf innerhalb Windows PowerShell Laufzeit beschränkt ist, z. B. set-variable
. Cmdlets, die eine permanente Änderung ausführen oder nicht, sollten SupportsShouldProcess
System.Management.Automation.Cmdlet.ShouldProcess nur dann deklarieren und aufrufen, wenn sie eine dauerhafte Änderung ausführen möchten.
Hinweis
Die ShouldProcess-Bestätigung gilt nur für Cmdlets. Wenn ein Befehl oder Skript den Ausführungsstatus eines Systems ändert, indem er .NET-Methoden oder -Eigenschaften direkt aufruft oder Anwendungen außerhalb von Windows PowerShell aufruft, ist diese Form der Bestätigung nicht verfügbar.
Das StopProc-Cmdlet
In diesem Thema wird ein Stop-Proc-Cmdlet beschrieben, das versucht, Prozesse zu beenden, die mit dem cmdlet Get-Proc abgerufen werden (beschrieben unter Creating Your First Cmdlet).
Definieren des Cmdlets
Der erste Schritt bei der Cmdlet-Erstellung besteht immer im Benennen des Cmdlets und deklarieren der .NET-Klasse, die das Cmdlet implementiert. Da Sie ein Cmdlet schreiben, um das System zu ändern, sollte es entsprechend benannt werden. Dieses Cmdlet beendet Systemprozesse, daher ist der hier ausgewählte Verbname "Stop", definiert durch die System.Management.Automation.Verbslifecycle-Klasse, mit dem Substantiv "Proc", um anzugeben, dass das Cmdlet Prozesse beendet. Weitere Informationen zu genehmigten Cmdlet-Verben finden Sie unter Cmdlet-Verbnamen.
Im Folgenden finden Sie die Klassendefinition für dieses Stop-Proc Cmdlet.
[Cmdlet(VerbsLifecycle.Stop, "Proc",
SupportsShouldProcess = true)]
public class StopProcCommand : Cmdlet
Beachten Sie, dass in der System.Management.Automation.CmdletAttribute-Deklaration das Attributschlüsselwort auf festgelegt ist, damit das Cmdlet Aufrufe an SupportsShouldProcess
true
System.Management.Automation.Cmdlet.ShouldProcess und System.Management.Automation.Cmdlet.ShouldContinueausführen kann.
Wenn dieses Schlüsselwort nicht festgelegt ist, sind die Parameter und Confirm
für den Benutzer nicht WhatIf
verfügbar.
Extrem destruktive Aktionen
Einige Vorgänge sind äußerst destruktiv, z. B. das Neuformatieren einer aktiven Festplattenpartition. In diesen Fällen sollte das Cmdlet beim ConfirmImpact
= ConfirmImpact.High
Deklarieren des Attributs System.Management.Automation.CmdletAttribute festgelegt werden. Diese Einstellung erzwingt, dass das Cmdlet eine Benutzerbestätigung angibt, auch wenn der Benutzer den Parameter nicht angegeben Confirm
hat. Cmdlet-Entwickler sollten jedoch eine Überbenutzerung für Vorgänge vermeiden, die nur potenziell destruktiv sind, z. B. das Löschen ConfirmImpact
eines Benutzerkontos. Denken Sie daran, ConfirmImpact
dass , wenn auf System.Management.Automation.ConfirmImpact
High festgelegt ist.
Ebenso ist es unwahrscheinlich, dass einige Vorgänge destruktiv sind, obwohl sie theoretisch den Ausführungszustand eines Systems außerhalb der Windows PowerShell. Solche Cmdlets können auf ConfirmImpact
System.Management.Automation.Confirmimpact.Low festgelegt werden.
Dadurch werden Bestätigungsanforderungen umgangen, bei denen der Benutzer aufgefordert wurde, nur Vorgänge mit mittleren und hohen Auswirkungen zu bestätigen.
Definieren von Parametern für die Systemänderung
In diesem Abschnitt wird beschrieben, wie Sie die Cmdlet-Parameter definieren, einschließlich der Parameter, die zur Unterstützung von Systemänderungen erforderlich sind. Weitere Informationen zum Definieren von Parametern finden Sie unter Hinzufügen von Parametern, die Befehlszeileneingaben verarbeiten.
Das Stop-Proc-Cmdlet definiert drei Parameter: Name
Force
, und PassThru
.
Der Name
-Parameter entspricht der Name
-Eigenschaft des Prozesseingabeobjekts. Beachten Sie, dass der Parameter in diesem Beispiel obligatorisch ist, da das Cmdlet fehlschlägt, wenn kein benannter Prozess Name
zum Beenden vorgibt.
Mit Force
dem Parameter kann der Benutzer Aufrufe von System.Management.Automation.Cmdlet.ShouldContinue überschreiben.
Tatsächlich sollte jedes Cmdlet, das System.Management.Automation.Cmdlet.ShouldContinue aufruft, über einen Parameter verfügen, sodass das Cmdlet, wenn angegeben wird, den Aufruf von Force
Force
System.Management.Automation.Cmdlet.ShouldContinue überspringt und mit dem Vorgang fortschreitet. Beachten Sie, dass dies keine Auswirkungen auf Aufrufe von System.Management.Automation.Cmdlet.ShouldProcess hat.
Mit dem Parameter kann der Benutzer angeben, ob das Cmdlet ein Ausgabeobjekt über die Pipeline übergibt, in diesem Fall, nachdem ein PassThru
Prozess beendet wurde. Beachten Sie, dass dieser Parameter an das Cmdlet selbst und nicht an eine Eigenschaft des Eingabeobjekts gebunden ist.
Dies ist die Parameterdeklaration für das Stop-Proc Cmdlet.
[Parameter(
Position = 0,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true
)]
public string[] Name
{
get { return processNames; }
set { processNames = value; }
}
private string[] processNames;
/// <summary>
/// Specify the Force parameter that allows the user to override
/// the ShouldContinue call to force the stop operation. This
/// parameter should always be used with caution.
/// </summary>
[Parameter]
public SwitchParameter Force
{
get { return force; }
set { force = value; }
}
private bool force;
/// <summary>
/// Specify the PassThru parameter that allows the user to specify
/// that the cmdlet should pass the process object down the pipeline
/// after the process has been stopped.
/// </summary>
[Parameter]
public SwitchParameter PassThru
{
get { return passThru; }
set { passThru = value; }
}
private bool passThru;
Überschreiben einer Eingabeverarbeitungsmethode
Das Cmdlet muss eine Eingabeverarbeitungsmethode überschreiben. Der folgende Code veranschaulicht die System.Management.Automation.Cmdlet.ProcessRecord-Überschreibung, die im Beispiel für Stop-Proc wird. Für jeden angeforderten Prozessnamen stellt diese Methode sicher, dass der Prozess kein spezieller Prozess ist, versucht, den Prozess zu beenden, und sendet dann ein Ausgabeobjekt, wenn der Parameter PassThru
angegeben ist.
protected override void ProcessRecord()
{
foreach (string name in processNames)
{
// For every process name passed to the cmdlet, get the associated
// process(es). For failures, write a non-terminating error
Process[] processes;
try
{
processes = Process.GetProcessesByName(name);
}
catch (InvalidOperationException ioe)
{
WriteError(new ErrorRecord(ioe,"Unable to access the target process by name",
ErrorCategory.InvalidOperation, name));
continue;
}
// Try to stop the process(es) that have been retrieved for a name
foreach (Process process in processes)
{
string processName;
try
{
processName = process.ProcessName;
}
catch (Win32Exception e)
{
WriteError(new ErrorRecord(e, "ProcessNameNotFound",
ErrorCategory.ReadError, process));
continue;
}
// Call Should Process to confirm the operation first.
// This is always false if WhatIf is set.
if (!ShouldProcess(string.Format("{0} ({1})", processName,
process.Id)))
{
continue;
}
// Call ShouldContinue to make sure the user really does want
// to stop a critical process that could possibly stop the computer.
bool criticalProcess =
criticalProcessNames.Contains(processName.ToLower());
if (criticalProcess &&!force)
{
string message = String.Format
("The process \"{0}\" is a critical process and should not be stopped. Are you sure you wish to stop the process?",
processName);
// It is possible that ProcessRecord is called multiple times
// when the Name parameter receives objects as input from the
// pipeline. So to retain YesToAll and NoToAll input that the
// user may enter across multiple calls to ProcessRecord, this
// information is stored as private members of the cmdlet.
if (!ShouldContinue(message, "Warning!",
ref yesToAll,
ref noToAll))
{
continue;
}
} // if (criticalProcess...
// Stop the named process.
try
{
process.Kill();
}
catch (Exception e)
{
if ((e is Win32Exception) || (e is SystemException) ||
(e is InvalidOperationException))
{
// This process could not be stopped so write
// a non-terminating error.
string message = String.Format("{0} {1} {2}",
"Could not stop process \"", processName,
"\".");
WriteError(new ErrorRecord(e, message,
ErrorCategory.CloseError, process));
continue;
} // if ((e is...
else throw;
} // catch
// If the PassThru parameter argument is
// True, pass the terminated process on.
if (passThru)
{
WriteObject(process);
}
} // foreach (Process...
} // foreach (string...
} // ProcessRecord
Aufrufen der ShouldProcess-Methode
Die Eingabeverarbeitungsmethode Ihres Cmdlets sollte die System.Management.Automation.Cmdlet.ShouldProcess-Methode aufrufen, um die Ausführung eines Vorgangs zu bestätigen, bevor eine Änderung (z. B. das Löschen von Dateien) am Ausführungszustand des Systems vorgenommen wird. Dadurch kann die Windows PowerShell Runtime das richtige WhatIf- und Confirm-Verhalten in der Shell liefern.
Hinweis
Wenn ein Cmdlet besagt, dass es verarbeiten soll und den System.Management.Automation.Cmdlet.ShouldProcess-Aufruf nicht ausführen kann, kann der Benutzer das System unerwartet ändern.
Der Aufruf von System.Management.Automation.Cmdlet.ShouldProcess sendet den Namen der Ressource, die geändert werden soll, an den Benutzer. Dabei berücksichtigt die Windows PowerShell-Runtime alle Befehlszeileneinstellungen oder Einstellungsvariablen, um zu bestimmen, was dem Benutzer angezeigt werden soll.
Das folgende Beispiel zeigt den Aufruf von System.Management.Automation.Cmdlet.ShouldProcess aus der Überschreibung der System.Management.Automation.Cmdlet.ProcessRecord-Methode im Stop-Proc Cmdlet.
if (!ShouldProcess(string.Format("{0} ({1})", processName,
process.Id)))
{
continue;
}
Aufrufen der ShouldContinue-Methode
Der Aufruf der System.Management.Automation.Cmdlet.ShouldContinue-Methode sendet eine sekundäre Nachricht an den Benutzer. Dieser Aufruf erfolgt nach dem Aufruf von System.Management.Automation.Cmdlet.ShouldProcess und , wenn der Parameter true
nicht auf festgelegt Force
true
wurde. Der Benutzer kann dann Feedback geben, um zu sagen, ob der Vorgang fortgesetzt werden soll. Ihr Cmdlet ruft System.Management.Automation.Cmdlet.ShouldContinue als zusätzliche Überprüfung auf potenziell gefährlichen Systemänderungen auf oder wenn Sie dem Benutzer Ja-zu-Alle- und Nein-zu-Alle-Optionen bereitstellen möchten.
Das folgende Beispiel zeigt den Aufruf von System.Management.Automation.Cmdlet.ShouldContinue aus der Außerkraftsetzung der System.Management.Automation.Cmdlet.ProcessRecord-Methode im Beispiel-Stop-Proc Cmdlet.
if (criticalProcess &&!force)
{
string message = String.Format
("The process \"{0}\" is a critical process and should not be stopped. Are you sure you wish to stop the process?",
processName);
// It is possible that ProcessRecord is called multiple times
// when the Name parameter receives objects as input from the
// pipeline. So to retain YesToAll and NoToAll input that the
// user may enter across multiple calls to ProcessRecord, this
// information is stored as private members of the cmdlet.
if (!ShouldContinue(message, "Warning!",
ref yesToAll,
ref noToAll))
{
continue;
}
} // if (criticalProcess...
Beenden der Eingabeverarbeitung
Die Eingabeverarbeitungsmethode eines Cmdlets, das Systemänderungen vorsteuert, muss eine Möglichkeit bieten, die Verarbeitung der Eingabe zu beenden. Im Fall dieses Stop-Proc-Cmdlets erfolgt ein Aufruf der System.Management.Automation.Cmdlet.ProcessRecord-Methode an die System.Diagnostics.Process.Kill*-Methode. Da der Parameter auf festgelegt ist, ruft PassThru
true
System.Management.Automation.Cmdlet.ProcessRecord auch System.Management.Automation.Cmdlet.WriteObject auf, um das Prozessobjekt an die Pipeline zu senden.
Codebeispiel
Den vollständigen C#-Beispielcode finden Sie unter StopProcessSample01-Beispiel.
Definieren von Objekttypen und Formatierung
Windows PowerShell übergibt Informationen zwischen Cmdlets mithilfe von .NET-Objekten. Folglich muss ein Cmdlet möglicherweise seinen eigenen Typ definieren, oder das Cmdlet muss einen vorhandenen Typ erweitern, der von einem anderen Cmdlet bereitgestellt wird. Weitere Informationen zum Definieren neuer Typen oder zum Erweitern vorhandener Typen finden Sie unter Erweitern von Objekttypen und Formatieren von.
Erstellen des Cmdlets
Nach der Implementierung eines Cmdlets muss es über ein Windows PowerShell über ein Windows PowerShell-Snap-In registriert werden. Weitere Informationen zum Registrieren von Cmdlets finden Sie unter Registrieren von Cmdlets, Anbietern und Hostanwendungen.
Testen des Cmdlets
Wenn Ihr Cmdlet bei Windows PowerShell wurde, können Sie es testen, indem Sie es in der Befehlszeile ausführen. Im Folgenden finden Sie mehrere Tests, die das Stop-Proc testen. Weitere Informationen zur Verwendung von Cmdlets über die Befehlszeile finden Sie unter Erste Schritte mit Windows PowerShell.
Starten Windows PowerShell, und verwenden Sie das cmdlet Stop-Proc, um die Verarbeitung wie unten dargestellt zu beenden. Da das Cmdlet den Parameter
Name
als obligatorisch angibt, fragt das Cmdlet den Parameter ab.PS> stop-proc
Die folgende Ausgabe wird angezeigt.
Cmdlet stop-proc at command pipeline position 1 Supply values for the following parameters: Name[0]:
Nun verwenden wir das Cmdlet , um den Prozess mit dem Namen "NOTEPAD" zu beenden. Das Cmdlet fordert Sie auf, die Aktion zu bestätigen.
PS> stop-proc -Name notepad
Die folgende Ausgabe wird angezeigt.
Confirm Are you sure you want to perform this action? Performing operation "stop-proc" on Target "notepad (4996)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y
Verwenden Stop-Proc wie gezeigt, um den kritischen Prozess mit dem Namen "WINLOGON" zu beenden. Sie werden dazu aufgefordert und gewarnt, dass diese Aktion ausgeführt wird, da dies dazu führen wird, dass das Betriebssystem neu gestartet wird.
PS> stop-proc -Name Winlogon
Die folgende Ausgabe wird angezeigt.
Confirm Are you sure you want to perform this action? Performing operation "stop-proc" on Target "winlogon (656)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y Warning! The process " winlogon " is a critical process and should not be stopped. Are you sure you wish to stop the process? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): N
Versuchen wir nun, den WINLOGON-Prozess zu beenden, ohne eine Warnung zu erhalten. Beachten Sie, dass dieser Befehlseintrag den
Force
Parameter verwendet, um die Warnung zu überschreiben.PS> stop-proc -Name winlogon -Force
Die folgende Ausgabe wird angezeigt.
Confirm Are you sure you want to perform this action? Performing operation "stop-proc" on Target "winlogon (656)". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): N
Weitere Informationen
Hinzufügen von Parametern, die Command-Line verarbeiten
Erweitern von Objekttypen und Formatierung