Freigeben über


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.

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

Registrieren von Cmdlets, Anbietern und Hostanwendungen

Windows PowerShell SDK

Cmdlet-Beispiele