Tworzenie polecenia cmdlet, które modyfikuje system

Czasami polecenie cmdlet musi zmodyfikować stan działania systemu, a nie tylko stan Windows PowerShell uruchomieniowego. W takich przypadkach polecenie cmdlet powinno umożliwić użytkownikowi potwierdzenie, czy wprowadzić zmianę.

Aby zapewnić obsługę potwierdzenia, polecenie cmdlet musi wykonać dwie czynności.

Obsługując potwierdzenie, polecenie cmdlet uwidacznia parametry i , które są dostarczane przez program Windows PowerShell, a także spełnia wytyczne programowe dotyczące polecenia cmdlet (aby uzyskać więcej informacji na temat wytycznych dotyczących tworzenia polecenia Confirm WhatIf cmdlet, zobacz Cmdlet Development Guidelines.).

Zmienianie systemu

Działanie "zmiany systemu" odnosi się do dowolnego polecenia cmdlet, które potencjalnie zmienia stan systemu poza Windows PowerShell. Na przykład zatrzymanie procesu, włączenie lub wyłączenie konta użytkownika albo dodanie wiersza do tabeli bazy danych to wszystkie zmiany w systemie, które należy potwierdzić. Z kolei operacje odczytu danych lub nawiązywania przejściowych połączeń nie zmieniają systemu i zazwyczaj nie wymagają potwierdzenia. Potwierdzenie nie jest również wymagane w przypadku akcji, których efekt jest ograniczony do wewnątrz Windows PowerShell uruchomieniowego, takich jak set-variable . Polecenia cmdlet, które mogą lub nie mogą wprowadzić trwałej zmiany, powinny deklarować i wywołać polecenie SupportsShouldProcess System.Management.Automation.Cmdlet.ShouldProcess tylko wtedy, gdy mają wprowadzić trwałą zmianę.

Uwaga

Potwierdzenie shouldProcess dotyczy tylko polecenia cmdlet. Jeśli polecenie lub skrypt modyfikuje stan działania systemu przez bezpośrednie wywołanie metod lub właściwości .NET lub przez wywołanie aplikacji spoza Windows PowerShell, ta forma potwierdzenia nie będzie dostępna.

Polecenie cmdlet StopProc

W tym temacie opisano Stop-Proc cmdlet, które próbuje zatrzymać procesy pobierane przy użyciu polecenia cmdlet Get-Proc (opisanego w temacie Creating Your First Cmdlet).

Definiowanie polecenia cmdlet

Pierwszym krokiem podczas tworzenia polecenia cmdlet jest zawsze nazewnictwo polecenia cmdlet i deklarowanie klasy .NET, która implementuje polecenie cmdlet. Ponieważ piszesz polecenie cmdlet w celu zmiany systemu, powinno ono mieć odpowiednie nazwy. To polecenie cmdlet zatrzymuje procesy systemowe, więc wybrana tutaj nazwa czasownika to "Stop", zdefiniowana przez klasę System.Management.Automation.Verbslifecycle, z rzeczownikiem "Proc", aby wskazać, że polecenie cmdlet zatrzymuje procesy. Aby uzyskać więcej informacji na temat zatwierdzonych czasowników cmdlet, zobacz Nazwy czasowników polecenia cmdlet.

Poniżej przedstawiono definicję klasy dla tego Stop-Proc cmdlet.

[Cmdlet(VerbsLifecycle.Stop, "Proc",
        SupportsShouldProcess = true)]
public class StopProcCommand : Cmdlet

Należy pamiętać, że w deklaracji System.Management.Automation.CmdletAttribute słowo kluczowe atrybutu jest ustawione na wartość , aby umożliwić poleceniem cmdlet w celu wywołania do SupportsShouldProcess true system.Management.Automation.Cmdlet.ShouldProcess i System.Management.Automation.Cmdlet.ShouldContinue. Bez tego słowa kluczowego ustawione Confirm parametry i nie będą dostępne dla WhatIf użytkownika.

Niezwykle destrukcyjne akcje

Niektóre operacje są niezwykle destrukcyjne, takie jak ponownie sformatowanie aktywnej partycji dysku twardego. W takich przypadkach polecenie cmdlet powinno zostać ustawione ConfirmImpact = ConfirmImpact.High podczas deklarowania atrybutu System.Management.Automation.CmdletAttribute. To ustawienie wymusza żądanie potwierdzenia przez polecenie cmdlet nawet wtedy, gdy użytkownik nie poda Confirm parametru . Jednak deweloperzy polecenia cmdlet powinni unikać nadwyżek dla operacji, które są po prostu potencjalnie destrukcyjne, takich jak ConfirmImpact usunięcie konta użytkownika. Pamiętaj, że jeśli ConfirmImpact jest ustawiona wartość System.Management.Automation.ConfirmImpact High.

Podobnie niektóre operacje są mało prawdopodobne do destrukcyjnych, chociaż teoretycznie modyfikują stan działania systemu poza Windows PowerShell. Takie polecenia cmdlet można ustawić ConfirmImpact na System.Management.Automation.Confirmimpact.Low. Spowoduje to obejście żądań potwierdzenia, w przypadku których użytkownik poprosił o potwierdzenie tylko operacji o średnim i dużym wpływie.

Definiowanie parametrów modyfikacji systemu

W tej sekcji opisano sposób definiowania parametrów polecenia cmdlet, w tym tych, które są potrzebne do obsługi modyfikacji systemu. Aby uzyskać ogólne informacje na temat definiowania parametrów, zobacz Adding Parameters that Process CommandLine Input (Dodawanie parametrów przetwarzających dane wejściowe wiersza polecenia).

Polecenie cmdlet Stop-Proc definiuje trzy parametry: Name Force , i PassThru .

Parametr Name odpowiada właściwości obiektu Name wejściowego procesu. Należy pamiętać, że parametr w tym przykładzie jest obowiązkowy, ponieważ polecenie cmdlet zakończy się niepowodzeniem, jeśli nie ma nazwanego procesu do Name zatrzymania.

Parametr Force umożliwia użytkownikowi przesłonięcie wywołań metody System.Management.Automation.Cmdlet.ShouldContinue. W rzeczywistości każde polecenie cmdlet, które wywołuje system.Management.Automation.Cmdlet.ShouldContinue, powinno mieć parametr , dzięki czemu po jego podaniem polecenie cmdlet pomija wywołanie funkcji Force Force System.Management.Automation.Cmdlet.ShouldContinue i kontynuuje operację. Należy pamiętać, że nie ma to wpływu na wywołania interfejsu System.Management.Automation.Cmdlet.ShouldProcess.

Parametr umożliwia użytkownikowi wskazanie, czy polecenie cmdlet przekazuje obiekt wyjściowy przez potok, w tym przypadku PassThru po zatrzymaniu procesu. Należy pamiętać, że ten parametr jest powiązany z samym poleceniem cmdlet, a nie z właściwością obiektu wejściowego.

Oto deklaracja parametru dla polecenia cmdlet Stop-Proc .

[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;

Zastępowanie metody przetwarzania danych wejściowych

Polecenie cmdlet musi zastąpić metodę przetwarzania danych wejściowych. Poniższy kod ilustruje przesłonięcie System.Management.Automation.Cmdlet.ProcessRecord używane w przykładowym Stop-Proc cmdlet. Dla każdej nazwy żądanego procesu ta metoda zapewnia, że proces nie jest procesem specjalnym, próbuje zatrzymać proces, a następnie wysyła obiekt wyjściowy, jeśli PassThru określono parametr.

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

Wywoływanie metody ShouldProcess

Metoda przetwarzania danych wejściowych polecenia cmdlet powinna wywołać metodę System.Management.Automation.Cmdlet.ShouldProcess, aby potwierdzić wykonanie operacji przed wprowadzeniem zmiany (na przykład usunięcia plików) do stanu uruchomienia systemu. Dzięki temu Windows PowerShell uruchomieniowe może podać poprawne zachowanie "WhatIf" i "Confirm" w obrębie powłoki.

Uwaga

Jeśli polecenie cmdlet, które obsługuje, powinno przetworzyć i nie może wykonać wywołania System.Management.Automation.Cmdlet.ShouldProcess, użytkownik może nieoczekiwanie zmodyfikować system.

Wywołanie elementu System.Management.Automation.Cmdlet.ShouldProcess wysyła nazwę zasobu, który ma zostać zmieniony, do użytkownika, przy czym środowisko uruchomieniowe programu Windows PowerShell uwzględnia wszystkie ustawienia wiersza polecenia lub zmienne preferencji podczas określania tego, co powinno być wyświetlane użytkownikowi.

W poniższym przykładzie pokazano wywołanie metody System.Management.Automation.Cmdlet.ShouldProcess z zastąpienia metody System.Management.Automation.Cmdlet.ProcessRecord w przykładowym Stop-Proc cmdlet.

if (!ShouldProcess(string.Format("{0} ({1})", processName,
                   process.Id)))
{
  continue;
}

Wywoływanie metody ShouldContinue

Wywołanie metody System.Management.Automation.Cmdlet.ShouldContinue wysyła komunikat pomocniczy do użytkownika. To wywołanie jest wykonane po wywołaniu metody System.Management.Automation.Cmdlet.ShouldProcess zwraca wartość , a jeśli parametr nie true został ustawiony na Force true . Użytkownik może następnie przekazać opinię, aby powiedzieć, czy operacja powinna być kontynuowana. Polecenie cmdlet wywołuje element System.Management.Automation.Cmdlet.ShouldContinue jako dodatkowe sprawdzenie potencjalnie niebezpiecznych modyfikacji systemu lub gdy użytkownik chce udostępnić użytkownikowi opcje "tak do wszystkich" i "nie do wszystkich".

W poniższym przykładzie pokazano wywołanie metody System.Management.Automation.Cmdlet.ShouldContinue z zastąpienia metody System.Management.Automation.Cmdlet.ProcessRecord w przykładowym 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...

Zatrzymywanie przetwarzania danych wejściowych

Metoda przetwarzania danych wejściowych polecenia cmdlet, która wprowadza modyfikacje systemu, musi umożliwiać zatrzymanie przetwarzania danych wejściowych. W przypadku tego polecenia cmdlet Stop-Proc wywołanie metody System.Management.Automation.Cmdlet.ProcessRecord do metody System.Diagnostics.Process.Kill*. Ponieważ parametr jest ustawiony na PassThru true wartość , system.Management.Automation.Cmdlet.ProcessRecord wywołuje również polecenie System.Management.Automation.Cmdlet.WriteObject w celu wysłania obiektu procesu do potoku.

Przykład kodu

Aby uzyskać kompletny przykładowy kod w języku C#, zobacz StopProcessSample01 Sample (Przykład StopProcessSample01).

Definiowanie typów obiektów i formatowania

Windows PowerShell przekazuje informacje między poleceniami cmdlet przy użyciu obiektów .Net. W związku z tym polecenie cmdlet może wymagać zdefiniowania własnego typu lub może być konieczne rozszerzenie istniejącego typu udostępnianego przez inne polecenie cmdlet. Aby uzyskać więcej informacji na temat definiowania nowych typów lub rozszerzania istniejących typów, zobacz Rozszerzanie typów obiektów i formatowanie.

Budowania polecenia cmdlet

Po zaimplementowaniu polecenia cmdlet należy je zarejestrować w Windows PowerShell za pośrednictwem Windows PowerShell przystawki. Aby uzyskać więcej informacji na temat rejestrowania cmdlet, zobacz How to Register Cmdlets, Providers, and Host Applications(Jak rejestrować polecenia cmdlet, dostawców i aplikacje hosta).

Testowanie polecenia cmdlet

Po zarejestrowaniu polecenia cmdlet za pomocą Windows PowerShell można je przetestować, uruchamiając je w wierszu polecenia. Oto kilka testów, które testują Stop-Proc cmdlet. Aby uzyskać więcej informacji na temat używania poleceń cmdlet z wiersza polecenia, zobacz Wprowadzenie z Windows PowerShell.

  • Uruchom Windows PowerShell i użyj polecenia cmdlet Stop-Proc, aby zatrzymać przetwarzanie, jak pokazano poniżej. Ponieważ polecenie cmdlet określa Name parametr jako obowiązkowy, polecenie cmdlet wykonuje zapytanie dotyczące parametru.

    PS> stop-proc
    

    Wyświetlone są następujące dane wyjściowe.

    Cmdlet stop-proc at command pipeline position 1
    Supply values for the following parameters:
    Name[0]:
    
  • Teraz użyjemy polecenia cmdlet , aby zatrzymać proces o nazwie "NOTEPAD". Polecenie cmdlet prosi o potwierdzenie akcji.

    PS> stop-proc -Name notepad
    

    Wyświetlone są następujące dane wyjściowe.

    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
    
  • Użyj Stop-Proc jak pokazano, aby zatrzymać krytyczny proces o nazwie "WINLOGON". Zostanie wyświetlony monit z ostrzeżeniem o wykonaniu tej akcji, ponieważ spowoduje to ponowne uruchomienie systemu operacyjnego.

    PS> stop-proc -Name Winlogon
    

    Wyświetlone są następujące dane wyjściowe.

    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
    
  • Spróbujmy teraz zatrzymać proces WINLOGON bez otrzymywania ostrzeżenia. Należy pamiętać, że ten wpis polecenia używa Force parametru w celu zastąpienia ostrzeżenia.

    PS> stop-proc -Name winlogon -Force
    

    Wyświetlone są następujące dane wyjściowe.

    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
    

Zobacz też

Dodawanie parametrów, które przetwarzają Command-Line danych wejściowych

Rozszerzanie typów obiektów i formatowanie

Jak rejestrować polecenia cmdlet, dostawców i aplikacje hosta

Windows PowerShell SDK

Przykłady poleceń cmdlet