Creazione di un cmdlet che modifica il sistema

A volte un cmdlet deve modificare lo stato di esecuzione del sistema, non solo lo stato del Windows PowerShell runtime. In questi casi, il cmdlet deve consentire all'utente di confermare se apportare o meno la modifica.

Per supportare la conferma, un cmdlet deve eseguire due operazioni.

Supportando la conferma, un cmdlet espone i parametri e forniti da Windows PowerShell e soddisfa anche le linee guida per lo sviluppo per i cmdlet . Per altre informazioni sulle linee guida per lo sviluppo dei cmdlet, vedere Linee guida per lo sviluppo di Confirm WhatIf cmdlet.

Modifica del sistema

L'azione di "modifica del sistema" si riferisce a qualsiasi cmdlet che potenzialmente modifica lo stato del sistema all'esterno Windows PowerShell. Ad esempio, l'arresto di un processo, l'abilitazione o la disabilitazione di un account utente o l'aggiunta di una riga a una tabella di database sono tutte modifiche al sistema che devono essere confermate. Al contrario, le operazioni che leggono i dati o stabiliscono connessioni temporanee non modificano il sistema e in genere non richiedono la conferma. La conferma non è necessaria anche per le azioni il cui effetto è limitato all'interno Windows PowerShell runtime, ad esempio set-variable . I cmdlet che potrebbero o meno apportare una modifica persistente devono dichiarare e chiamare SupportsShouldProcess System.Management.Automation.Cmdlet.ShouldProcess solo se stanno per apportare una modifica permanente.

Nota

La conferma di ShouldProcess si applica solo ai cmdlet. Se un comando o uno script modifica lo stato di esecuzione di un sistema chiamando direttamente metodi o proprietà .NET o chiamando applicazioni all'esterno di Windows PowerShell, questa forma di conferma non sarà disponibile.

The StopProc Cmdlet

Questo argomento descrive un cmdlet Stop-Proc che tenta di arrestare i processi recuperati usando il cmdlet Get-Proc (descritto in Creazione del primo cmdlet).

Definizione del cmdlet

Il primo passaggio nella creazione dei cmdlet consiste sempre nel denominare il cmdlet e dichiarare la classe .NET che implementa il cmdlet. Poiché si sta scrivendo un cmdlet per modificare il sistema, il nome deve essere denominato di conseguenza. Questo cmdlet arresta i processi di sistema, quindi il nome del verbo scelto qui è "Stop", definito dalla classe System.Management.Automation.Verbslifecycle, con il sostantivo "Proc" per indicare che il cmdlet arresta i processi. Per altre informazioni sui verbi dei cmdlet approvati, vedere Nomi dei verbi dei cmdlet.

Di seguito è riportata la definizione della classe per Stop-Proc cmdlet .

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

Tenere presente che nella dichiarazione System.Management.Automation.CmdletAttribute la parola chiave attribute è impostata su per consentire al cmdlet di effettuare chiamate a SupportsShouldProcess true System.Management.Automation.Cmdlet.ShouldProcess e System.Management.Automation.Cmdlet.ShouldContinue. Senza questa parola chiave impostata, Confirm i parametri e non saranno disponibili per WhatIf l'utente.

Azioni estremamente distruttive

Alcune operazioni sono estremamente distruttive, ad esempio la riformattazione di una partizione del disco rigido attiva. In questi casi, il cmdlet deve essere impostato ConfirmImpact = ConfirmImpact.High quando si dichiara l'attributo System.Management.Automation.CmdletAttribute. Questa impostazione forza il cmdlet a richiedere la conferma dell'utente anche quando l'utente non ha specificato il Confirm parametro . Gli sviluppatori di cmdlet, tuttavia, devono evitare di sovrautilizzo per operazioni potenzialmente distruttive, ad esempio ConfirmImpact l'eliminazione di un account utente. Tenere presente che ConfirmImpact se è impostato su System.Management.Automation.ConfirmImpact High.

Analogamente, è improbabile che alcune operazioni siano distruttive, anche se in teoria modificano lo stato di esecuzione di un sistema al di fuori Windows PowerShell. Tali cmdlet possono essere impostati ConfirmImpact su System.Management.Automation.Confirmimpact.Low. In questo modo verranno ignorate le richieste di conferma in cui l'utente ha chiesto di confermare solo operazioni a impatto medio e ad alto impatto.

Definizione dei parametri per la modifica del sistema

Questa sezione descrive come definire i parametri dei cmdlet, inclusi quelli necessari per supportare la modifica del sistema. Per informazioni generali sulla definizione dei parametri, vedere Aggiunta di parametri che elaborano l'input della riga di comando.

Il cmdlet Stop-Proc definisce tre parametri: Name , Force e PassThru .

Il Name parametro corrisponde alla proprietà Name dell'oggetto di input del processo. Tenere presente che il parametro in questo esempio è obbligatorio, perché il cmdlet avrà esito negativo se non ha Name un processo denominato da arrestare.

Il Force parametro consente all'utente di eseguire l'override delle chiamate a System.Management.Automation.Cmdlet.ShouldContinue. Di fatto, qualsiasi cmdlet che chiama System.Management.Automation.Cmdlet.ShouldContinue deve avere un parametro in modo che quando viene specificato, il cmdlet ignora la chiamata a Force Force System.Management.Automation.Cmdlet.ShouldContinue e procede con l'operazione. Tenere presente che ciò non influisce sulle chiamate a System.Management.Automation.Cmdlet.ShouldProcess.

Il parametro consente all'utente di indicare se il cmdlet passa un oggetto di output attraverso la pipeline, in questo caso PassThru dopo l'arresto di un processo. Tenere presente che questo parametro è associato al cmdlet stesso anziché a una proprietà dell'oggetto di input.

Ecco la dichiarazione di parametro per il 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;

Override di un metodo di elaborazione di input

Il cmdlet deve eseguire l'override di un metodo di elaborazione dell'input. Il codice seguente illustra l'override System.Management.Automation.Cmdlet.ProcessRecord usato nel cmdlet Stop-Proc esempio. Per ogni nome di processo richiesto, questo metodo garantisce che il processo non sia un processo speciale, tenta di arrestare il processo e quindi invia un oggetto di output se il PassThru parametro è specificato.

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

Chiamata del metodo ShouldProcess

Il metodo di elaborazione dell'input del cmdlet deve chiamare il metodo System.Management.Automation.Cmdlet.ShouldProcess per confermare l'esecuzione di un'operazione prima che venga apportata una modifica(ad esempio, l'eliminazione di file) allo stato di esecuzione del sistema. Ciò consente al runtime Windows PowerShell di fornire il comportamento "WhatIf" e "Confirm" corretti all'interno della shell.

Nota

Se un cmdlet dichiara di dover elaborare e non riesce a effettuare la chiamata a System.Management.Automation.Cmdlet.ShouldProcess, l'utente potrebbe modificare il sistema in modo imprevisto.

La chiamata a System.Management.Automation.Cmdlet.ShouldProcess invia il nome della risorsa da modificare all'utente, con il runtime di Windows PowerShell che prende in considerazione eventuali impostazioni della riga di comando o variabili di preferenza per determinare cosa deve essere visualizzato all'utente.

L'esempio seguente illustra la chiamata a System.Management.Automation.Cmdlet.ShouldProcess dall'override del metodo System.Management.Automation.Cmdlet.ProcessRecord nel cmdlet Stop-Proc esempio.

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

Chiamata del metodo ShouldContinue

La chiamata al metodo System.Management.Automation.Cmdlet.ShouldContinue invia un messaggio secondario all'utente. Questa chiamata viene effettuata dopo la chiamata a System.Management.Automation.Cmdlet.ShouldProcess restituisce e true se il parametro non è stato impostato su Force true . L'utente può quindi fornire commenti e suggerimenti per indicare se l'operazione deve essere continuata. Il cmdlet chiama System.Management.Automation.Cmdlet.ShouldContinue come controllo aggiuntivo per le modifiche di sistema potenzialmente pericolose o quando si vogliono fornire all'utente opzioni sì a tutti e no-to-all.

L'esempio seguente illustra la chiamata a System.Management.Automation.Cmdlet.ShouldContinue dall'override del metodo System.Management.Automation.Cmdlet.ProcessRecord nel cmdlet Stop-Proc esempio.

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...

Arresto dell'elaborazione dell'input

Il metodo di elaborazione dell'input di un cmdlet che apporta modifiche al sistema deve fornire un modo per arrestare l'elaborazione dell'input. Nel caso di questo cmdlet Stop-Proc, viene effettuata una chiamata dal metodo System.Management.Automation.Cmdlet.ProcessRecord al metodo System.Diagnostics.Process.Kill*. Poiché il parametro è PassThru impostato su true , System.Management.Automation.Cmdlet.ProcessRecord chiama anche System.Management.Automation.Cmdlet.WriteObject per inviare l'oggetto processo alla pipeline.

Codice di esempio

Per il codice di esempio C# completo, vedere StopProcessSample01 Sample.

Definizione di tipi di oggetto e formattazione

Windows PowerShell passa informazioni tra i cmdlet usando oggetti .NET. Di conseguenza, un cmdlet potrebbe dover definire il proprio tipo o il cmdlet potrebbe dover estendere un tipo esistente fornito da un altro cmdlet. Per altre informazioni sulla definizione di nuovi tipi o sull'estensione di tipi esistenti, vedere Estensione dei tipi di oggetto e formattazione.

Compilazione del cmdlet

Dopo l'implementazione di un cmdlet, è necessario registrarlo con Windows PowerShell tramite uno snap-in Windows PowerShell di esecuzione. Per altre informazioni sulla registrazione dei cmdlet, vedere How to Register Cmdlets, Providers, and Host Applications.

Test del cmdlet

Dopo aver registrato il cmdlet con Windows PowerShell, è possibile testarlo eseguendolo nella riga di comando. Di seguito sono disponibili diversi test che testano Stop-Proc cmdlet . Per altre informazioni sull'uso dei cmdlet dalla riga di comando, vedere l'Attività iniziali con Windows PowerShell.

  • Avviare Windows PowerShell e usare il cmdlet Stop-Proc per arrestare l'elaborazione, come illustrato di seguito. Poiché il cmdlet specifica il Name parametro come obbligatorio, il cmdlet esegue una query per il parametro.

    PS> stop-proc
    

    Viene visualizzato l'output seguente.

    Cmdlet stop-proc at command pipeline position 1
    Supply values for the following parameters:
    Name[0]:
    
  • A questo punto si userà il cmdlet per arrestare il processo denominato "NOTEPAD". Il cmdlet chiede di confermare l'azione.

    PS> stop-proc -Name notepad
    

    Viene visualizzato l'output seguente.

    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
    
  • Usare Stop-Proc come illustrato per arrestare il processo critico denominato "WINLOGON". Viene visualizzata una richiesta e viene visualizzato un avviso per l'esecuzione di questa azione perché il sistema operativo verrà riavviato.

    PS> stop-proc -Name Winlogon
    

    Viene visualizzato l'output seguente.

    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
    
  • Si proverà ora ad arrestare il processo WINLOGON senza ricevere un avviso. Tenere presente che questa voce di comando usa il Force parametro per eseguire l'override dell'avviso.

    PS> stop-proc -Name winlogon -Force
    

    Viene visualizzato l'output seguente.

    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
    

Vedere anche

Aggiunta di parametri che elaborano Command-Line input

Estensione dei tipi di oggetto e formattazione

Come registrare cmdlet, provider e applicazioni host

Windows PowerShell SDK

Esempi di cmdlet