Een cmdlet maken waarmee het systeem wordt gewijzigd

Soms moet een cmdlet de status van het systeem wijzigen, niet alleen de status van de Windows PowerShell runtime. In dergelijke gevallen moet de cmdlet de gebruiker de mogelijkheid bieden om te bevestigen of de wijziging wel of niet moet worden gewijzigd.

Ter ondersteuning van bevestiging moet een cmdlet twee dingen doen.

Door bevestiging te ondersteunen, toont een cmdlet de parameters en die worden geleverd door Windows PowerShell en voldoet ook aan de ontwikkelingsrichtlijnen voor Confirm WhatIf cmdlets (zie Cmdlet Development Guidelines(Ontwikkelingsrichtlijnen voor cmdlets) voor meer informatie over de ontwikkelingsrichtlijnen voor cmdlets.

Het systeem wijzigen

Het wijzigen van het systeem verwijst naar elke cmdlet die mogelijk de status van het systeem buiten de Windows PowerShell. Het stoppen van een proces, het in- of uitschakelen van een gebruikersaccount of het toevoegen van een rij aan een databasetabel zijn bijvoorbeeld alle wijzigingen in het systeem die moeten worden bevestigd. Bewerkingen die gegevens lezen of tijdelijke verbindingen tot stand brengen, wijzigen het systeem daarentegen niet en vereisen doorgaans geen bevestiging. Er is ook geen bevestiging nodig voor acties waarvan het effect beperkt is tot binnen Windows PowerShell runtime, zoals set-variable . Cmdlets die al dan niet een permanente wijziging kunnen aanroepen, moeten SupportsShouldProcess System.Management.Automation.Cmdlet.ShouldProcess alleen declareer en aanroepen als ze op het punt staan een permanente wijziging aan te brengen.

Notitie

ShouldProcess-bevestiging geldt alleen voor cmdlets. Als een opdracht of script de status van een systeem wijzigt door rechtstreeks .NET-methoden of -eigenschappen aan te roepen, of door toepassingen buiten Windows PowerShell aan te roepen, is deze vorm van bevestiging niet beschikbaar.

De Cmdlet StopProc

In dit onderwerp wordt een Stop-Proc cmdlet beschreven die probeert processen te stoppen die worden opgehaald met behulp van de Get-Proc-cmdlet (beschreven in Uw eerste cmdlet maken).

De cmdlet definiëren

De eerste stap bij het maken van de cmdlet is het altijd benoemen van de cmdlet en het declareren van de .NET-klasse die de cmdlet implementeert. Omdat u een cmdlet schrijft om het systeem te wijzigen, moet deze dienovereenkomstig worden genoemd. Deze cmdlet stopt systeemprocessen, dus de hier gekozen werkwoordnaam is 'Stoppen', gedefinieerd door de klasse System.Management.Automation.Verbslifecycle, met het zelfstandig naamwoord 'Proc' om aan te geven dat de cmdlet processen stopt. Zie cmdlet werkwoordnamen voor meer informatie over goedgekeurde cmdlet-woorden.

Hier volgt de klassedefinitie voor deze Stop-Proc cmdlet.

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

Let erop dat in de declaratie System.Management.Automation.CmdletAttribute het kenmerktrefwoord is ingesteld op om de cmdlet in staat te stellen om aanroepen naar SupportsShouldProcess true System.Management.Automation.Cmdlet.ShouldProcess en System.Management.Automation.Cmdlet.ShouldContinueuit te voeren. Zonder deze sleutelwoordset zijn Confirm de parameters en niet beschikbaar voor de WhatIf gebruiker.

Extreem destructieve acties

Sommige bewerkingen zijn zeer destructief, zoals het opnieuw opformatteren van een actieve hardeschijfpartitie. In dergelijke gevallen moet de cmdlet worden ingesteld bij het declareren van het kenmerk ConfirmImpact = ConfirmImpact.High System.Management.Automation.CmdletAttribute. Met deze instelling wordt de cmdlet gedwongen om gebruikersbevestiging aan te vragen, zelfs wanneer de gebruiker de parameter niet heeft Confirm opgegeven. Cmdlet-ontwikkelaars moeten echter voorkomen dat ze te veel gebruiken voor bewerkingen die mogelijk destructief zijn, zoals het verwijderen ConfirmImpact van een gebruikersaccount. Denk eraan dat als ConfirmImpact is ingesteld op System.Management.Automation.ConfirmImpact High.

Op dezelfde manier zijn sommige bewerkingen waarschijnlijk niet destructief, hoewel ze in theorie de status van een systeem buiten de Windows PowerShell. Dergelijke cmdlets kunnen worden ConfirmImpact ingesteld op System.Management.Automation.Confirmimpact.Low. Hiermee worden bevestigingsaanvragen overgeslagen waarbij de gebruiker heeft gevraagd om alleen bewerkingen met gemiddelde impact en hoge impact te bevestigen.

Parameters voor systeemwijziging definiëren

In deze sectie wordt beschreven hoe u de cmdlet-parameters definieert, inclusief de parameters die nodig zijn om systeemaanpassingen te ondersteunen. Zie Parameters toevoegen die opdrachtregelinvoer verwerken als u algemene informatie nodig hebt over het definiëren van parameters.

De Stop-Proc cmdlet definieert drie parameters: Name Force , en PassThru .

De Name parameter komt overeen met de eigenschap van het Name procesinvoerobject. Let erop dat de parameter in dit voorbeeld verplicht is, omdat de cmdlet mislukt als deze geen benoemd proces heeft Name om te stoppen.

Met de parameter kan de gebruiker aanroepen naar Force System.Management.Automation.Cmdlet.ShouldContinue overschrijven. In feite moet elke cmdlet die System.Management.Automation.Cmdlet.ShouldContinue aanroept, een parameter hebben, zodat wanneer is opgegeven, de cmdlet de aanroep naar Force Force System.Management.Automation.Cmdlet.ShouldContinue overslaat en doorgaat met de bewerking. Dit heeft geen invloed op aanroepen naar System.Management.Automation.Cmdlet.ShouldProcess.

Met de parameter kan de gebruiker aangeven of de cmdlet een uitvoerobject via de pijplijn doorgeeft, in dit geval nadat een PassThru proces is gestopt. Deze parameter is gekoppeld aan de cmdlet zelf in plaats van aan een eigenschap van het invoerobject.

Hier is de parameterdeclaratie voor de 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;

Een invoerverwerkingsmethode overschrijven

De cmdlet moet een invoerverwerkingsmethode overschrijven. De volgende code illustreert de overschrijvingen van System.Management.Automation.Cmdlet.ProcessRecord die worden gebruikt in de voorbeeld-Stop-Proc cmdlet. Voor elke aangevraagde procesnaam zorgt deze methode ervoor dat het proces geen speciaal proces is, probeert het proces te stoppen en verzendt vervolgens een uitvoerobject als de PassThru parameter is opgegeven.

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

De Methode ShouldProcess aanroepen

De invoerverwerkingsmethode van uw cmdlet moet de methode System.Management.Automation.Cmdlet.ShouldProcess aanroepen om de uitvoering van een bewerking te bevestigen voordat er een wijziging (bijvoorbeeld bestanden verwijderen) wordt aangebracht in de uitvoeringstoestand van het systeem. Hierdoor kan Windows PowerShell runtime het juiste WhatIf- en Confirm-gedrag in de shell leveren.

Notitie

Als een cmdlet verklaart dat deze ondersteuning moet verwerken en de aanroep System.Management.Automation.Cmdlet.ShouldProcess niet kan maken, kan de gebruiker het systeem onverwacht wijzigen.

De aanroep van System.Management.Automation.Cmdlet.ShouldProcess verzendt de naam van de resource die aan de gebruiker moet worden gewijzigd, waarbij de Windows PowerShell-runtime rekening houdt met opdrachtregelinstellingen of voorkeursvariabelen om te bepalen wat er aan de gebruiker moet worden weergegeven.

In het volgende voorbeeld ziet u de aanroep van System.Management.Automation.Cmdlet.ShouldProcess vanaf de overschrijvingen van de methode System.Management.Automation.Cmdlet.ProcessRecord in de voorbeeld-cmdlet Stop-Proc cmdlet.

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

De methode ShouldContinue aanroepen

De aanroep van de methode System.Management.Automation.Cmdlet.ShouldContinue verzendt een secundair bericht naar de gebruiker. Deze aanroep wordt gedaan na de aanroep van System.Management.Automation.Cmdlet.ShouldProcess en als de true parameter niet is ingesteld op Force true . De gebruiker kan vervolgens feedback geven om te zeggen of de bewerking moet worden voortgezet. Uw cmdlet roept System.Management.Automation.Cmdlet.ShouldContinue aan als een extra controle op mogelijk gevaarlijke systeemwijzigingen of wanneer u de gebruiker ja-op-alles- en nee-op-alles-opties wilt bieden.

In het volgende voorbeeld ziet u de aanroep van System.Management.Automation.Cmdlet.ShouldContinue vanuit de overschrijvingen van de methode System.Management.Automation.Cmdlet.ProcessRecord in de voorbeeld-cmdlet 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...

Invoerverwerking stoppen

De invoerverwerkingsmethode van een cmdlet waarmee systeemwijzigingen worden aangebracht, moet een manier bieden om de verwerking van invoer te stoppen. In het geval van deze Stop-Proc cmdlet wordt een aanroep gedaan vanuit de methode System.Management.Automation.Cmdlet.ProcessRecord naar de methode System.Diagnostics.Process.Kill*. Omdat de parameter is ingesteld op , roept PassThru true System.Management.Automation.Cmdlet.ProcessRecord ook System.Management.Automation.Cmdlet.WriteObject aan om het procesobject naar de pijplijn te verzenden.

Codevoorbeeld

Zie StopProcessSample01Sample voor de volledige C#-voorbeeldcode.

Objecttypen en -opmaak definiëren

Windows PowerShell geeft informatie door tussen cmdlets met behulp van .Net-objecten. Daarom moet een cmdlet mogelijk een eigen type definiëren, of moet de cmdlet mogelijk een bestaand type uitbreiden dat wordt geleverd door een andere cmdlet. Zie Extending Object Types and Formatting (Objecttypen uitbreiden en opmaak) voor meer informatie over het definiëren van nieuwe typen of het uitbreiden van bestaande typen.

De cmdlet bouwen

Nadat u een cmdlet hebt geïmplementeerd, moet deze worden geregistreerd bij Windows PowerShell via Windows PowerShell module. Zie Cmdlets, providers en hosttoepassingen registreren voor meer informatie over het registreren van cmdlets.

De cmdlet testen

Wanneer uw cmdlet is geregistreerd bij Windows PowerShell, kunt u deze testen door deze uit te voeren op de opdrachtregel. Hier zijn verschillende tests die de cmdlet Stop-Proc testen. Zie de Aan de slag met Windows PowerShell voor meer informatie over het gebruik van cmdlets vanaf de opdrachtregel.

  • Start Windows PowerShell en gebruik de Stop-Proc cmdlet om de verwerking te stoppen, zoals hieronder wordt weergegeven. Omdat de cmdlet de parameter als verplicht opgeeft, vraagt de Name cmdlet naar de parameter .

    PS> stop-proc
    

    De volgende uitvoer wordt weergegeven.

    Cmdlet stop-proc at command pipeline position 1
    Supply values for the following parameters:
    Name[0]:
    
  • We gaan nu de cmdlet gebruiken om het proces met de naam KLADBLOK te stoppen. De cmdlet vraagt u om de actie te bevestigen.

    PS> stop-proc -Name notepad
    

    De volgende uitvoer wordt weergegeven.

    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
    
  • Gebruik Stop-Proc zoals wordt weergegeven om het kritieke proces met de naam WINLOGON te stoppen. U wordt gevraagd en gewaarschuwd over het uitvoeren van deze actie, omdat het besturingssysteem hierdoor opnieuw wordt opgestart.

    PS> stop-proc -Name Winlogon
    

    De volgende uitvoer wordt weergegeven.

    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
    
  • We gaan nu proberen het WINLOGON-proces te stoppen zonder een waarschuwing te ontvangen. Let erop dat deze opdracht de Force parameter gebruikt om de waarschuwing te overschrijven.

    PS> stop-proc -Name winlogon -Force
    

    De volgende uitvoer wordt weergegeven.

    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
    

Zie ook

Parameters toevoegen die de invoer Command-Line verwerken

Objecttypen en -opmaak uitbreiden

Cmdlets, providers en hosttoepassingen registreren

Windows PowerShell SDK

Cmdlet-voorbeelden