Udostępnij za pośrednictwem


Tworzenie polecenia cmdlet, które modyfikuje system

Czasami polecenie cmdlet musi zmodyfikować stan działania systemu, a nie tylko stan środowiska uruchomieniowego programu Windows PowerShell. W takich przypadkach polecenie cmdlet powinno zezwolić użytkownikowi na potwierdzenie, czy należy wprowadzić zmianę.

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

Potwierdzając, polecenie cmdlet uwidacznia parametry Confirm i WhatIf dostarczane przez program Windows PowerShell, a także spełnia wytyczne programistyczne dla poleceń cmdlet (aby uzyskać więcej informacji na temat wytycznych dotyczących programowania poleceń cmdlet, zobacz Wytyczne dotyczące programowania poleceń cmdlet.).

Zmiana systemu

Czynność "zmiany systemu" odnosi się do dowolnego polecenia cmdlet, które potencjalnie zmienia stan systemu poza programem Windows PowerShell. Na przykład zatrzymanie procesu, włączenie lub wyłączenie konta użytkownika lub dodanie wiersza do tabeli bazy danych to wszystkie zmiany w systemie, które należy potwierdzić. Z kolei operacje odczytujące dane lub ustanawiania 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 środowiska uruchomieniowego programu Windows PowerShell, takich jak Set-Variable. Polecenia cmdlet, które mogą lub nie mogą wprowadzać trwałej zmiany, powinny deklarować SupportsShouldProcess i wywoływać System.Management.Automation.Cmdlet.ShouldProcess tylko wtedy, gdy mają one spowodować trwałą zmianę.

Uwaga

Potwierdzenie shouldProcess ma zastosowanie tylko do poleceń cmdlet. Jeśli polecenie lub skrypt modyfikuje stan działania systemu przez bezpośrednie wywoływanie metod lub właściwości platformy .NET lub wywoływanie aplikacji poza programem Windows PowerShell, ta forma potwierdzenia nie będzie dostępna.

Polecenie cmdlet StopProc

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

Definiowanie polecenia cmdlet

Pierwszym krokiem 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 być odpowiednio nazwane. To polecenie cmdlet zatrzymuje procesy systemowe, więc nazwa czasownika wybrana tutaj to "Stop", zdefiniowana przez System.Management.Automation.VerbsLifecycle klasy, z nounem "Proc", aby wskazać, że polecenie cmdlet zatrzymuje procesy. Aby uzyskać więcej informacji na temat zatwierdzonych czasowników poleceń cmdlet, zobacz Cmdlet Verb Names.

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

[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 SupportsShouldProcess jest ustawione na true, aby umożliwić poleceniem cmdlet nawiązywanie wywołań do System.Management.Automation.Cmdlet.ShouldProcess i System.Management.Automation.Cmdlet.ShouldContinue. Bez tego zestawu słów kluczowych parametry Confirm i WhatIf nie będą dostępne dla użytkownika.

Niezwykle destrukcyjne działania

Niektóre operacje są bardzo destrukcyjne, takie jak ponowne sformatowanie aktywnej partycji dysku twardego. W takich przypadkach polecenie cmdlet powinno ustawić ConfirmImpact = ConfirmImpact.High podczas deklarowania atrybutu System.Management.Automation.CmdletAttribute. To ustawienie wymusza żądanie potwierdzenia użytkownika, nawet jeśli użytkownik nie określił parametru Confirm. Jednak deweloperzy poleceń cmdlet powinni unikać nadmiernego uwzględnienia ConfirmImpact dla operacji, które są po prostu potencjalnie destrukcyjne, takie jak usuwanie konta użytkownika. Należy pamiętać, że jeśli ConfirmImpact ma ustawioną wartość System.Management.Automation.ConfirmImpactHigh.

Podobnie niektóre operacje są mało prawdopodobne, aby były destrukcyjne, chociaż teoretycznie modyfikują stan działania systemu poza programem Windows PowerShell. Takie polecenia cmdlet mogą ustawić ConfirmImpact na System.Management.Automation.ConfirmImpact.Low. Spowoduje to obejście żądań potwierdzenia, w których użytkownik poprosił o potwierdzenie tylko operacji o średnim wpływie 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. Zobacz Dodawanie parametrów, które przetwarzają dane wejściowe wiersza polecenia, jeśli potrzebujesz ogólnych informacji na temat definiowania parametrów.

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

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

Parametr Force umożliwia użytkownikowi zastąpienie wywołań System.Management.Automation.Cmdlet.ShouldContinue. W rzeczywistości każde polecenie cmdlet wywołujące System.Management.Automation.Cmdlet.ShouldContinue powinno mieć parametr Force, tak aby po określeniu Force polecenie cmdlet pomija wywołanie System.Management.Automation.Cmdlet.ShouldContinue i kontynuuje operację. Należy pamiętać, że nie ma to wpływu na wywołania System.Management.Automation.Cmdlet.ShouldProcess.

Parametr PassThru umożliwia użytkownikowi wskazanie, czy polecenie cmdlet przekazuje obiekt wyjściowy przez potok, w tym przypadku po zatrzymaniu procesu. Należy pamiętać, że ten parametr jest powiązany z samym poleceniem cmdlet zamiast 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 wejściowego

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

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 wejściowego polecenia cmdlet powinna wywołać metodę System.Management.Automation.Cmdlet.ShouldProcess, aby potwierdzić wykonanie operacji przed zmianą (na przykład usunięcie plików) w stanie uruchomienia systemu. Dzięki temu środowisko uruchomieniowe programu Windows PowerShell zapewnia prawidłowe zachowanie "WhatIf" i "Confirm" w powłoce.

Uwaga

Jeśli polecenie cmdlet wskazuje, że obsługuje ono proces i nie może wykonać wywołania System.Management.Automation.Cmdlet.ShouldProcess, użytkownik może nieoczekiwanie zmodyfikować system.

Wywołanie System.Management.Automation.Cmdlet.ShouldProcess wysyła nazwę zasobu, który ma zostać zmieniony na użytkownika, przy czym środowisko uruchomieniowe programu Windows PowerShell uwzględnia wszystkie ustawienia wiersza polecenia lub zmienne preferencji w określaniu, 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 poleceniu cmdlet Stop-Proc.

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

Wywoływanie metody ShouldContinue

Wywołanie metody System.Management.Automation.Cmdlet.ShouldContinue wysyła użytkownikowi komunikat pomocniczy. To wywołanie jest wykonywane po wywołaniu polecenia System.Management.Automation.Cmdlet.ShouldProcess zwraca true i jeśli parametr Force nie został ustawiony na wartość true. Użytkownik może następnie przekazać opinię, aby powiedzieć, czy operacja powinna być kontynuowana. Polecenie cmdlet wywołuje System.Management.Automation.Cmdlet.ShouldContinue jako dodatkową kontrolę pod kątem potencjalnie niebezpiecznych modyfikacji systemu lub gdy chcesz podać opcję tak do wszystkich i no-to-wszystkie opcje dla użytkownika.

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

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óre wprowadza modyfikacje systemu, musi zapewnić sposób zatrzymania przetwarzania danych wejściowych. W przypadku tego polecenia cmdlet Stop-Proc wywołanie jest wykonywane z System.Management.Automation.Cmdlet.ProcessRecord metody System.Diagnostics.Process.Kill*. Ponieważ parametr PassThru jest ustawiony na true, System.Management.Automation.Cmdlet.ProcessRecord również wywołuje System.Management.Automation.Cmdlet.WriteObject, aby wysłać obiekt procesu do potoku.

Przykładowy kod

Aby uzyskać pełny przykładowy kod języka C#, zobacz StopProcessSample01 Sample.

Definiowanie typów obiektów i formatowanie

Program Windows PowerShell przekazuje informacje między poleceniami cmdlet przy użyciu obiektów .NET. W związku z tym może być konieczne zdefiniowanie własnego typu polecenia cmdlet lub może być konieczne rozszerzenie istniejącego typu dostarczonego 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.

Kompilowanie polecenia cmdlet

Po zaimplementowaniu polecenia cmdlet należy go zarejestrować w programie Windows PowerShell za pomocą przystawki programu Windows PowerShell. Aby uzyskać więcej informacji na temat rejestrowania poleceń cmdlet, zobacz Jak rejestrować polecenia cmdlet, dostawcy i aplikacje hosta.

Testowanie polecenia cmdlet

Po zarejestrowaniu polecenia cmdlet w programie Windows PowerShell możesz go przetestować, uruchamiając je w wierszu polecenia. Poniżej przedstawiono kilka testów, które testują polecenie cmdlet Stop-Proc. Aby uzyskać więcej informacji na temat używania poleceń cmdlet z wiersza polecenia, zobacz Wprowadzenie do programu Windows PowerShell.

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

    PS> Stop-Proc
    

    Zostanie wyświetlone 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 "NOTATNIK". Polecenie cmdlet prosi o potwierdzenie akcji.

    PS> Stop-Proc -Name notepad
    

    Zostanie wyświetlone 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 i zostanie wyświetlony monit o wykonanie tej akcji, ponieważ spowoduje to ponowne uruchomienie systemu operacyjnego.

    PS> Stop-Proc -Name Winlogon
    

    Zostanie wyświetlone 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
    
  • Teraz spróbujmy zatrzymać proces WINLOGON bez otrzymania ostrzeżenia. Należy pamiętać, że ten wpis polecenia używa parametru Force do zastąpienia ostrzeżenia.

    PS> Stop-Proc -Name winlogon -Force
    

    Zostanie wyświetlone 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ą wejściowe Command-Line

rozszerzanie typów obiektów i formatowanie

Jak rejestrować polecenia cmdlet, dostawcy i aplikacje hosta

zestaw SDK programu Windows PowerShell

przykłady poleceń cmdlet