Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
A veces, un cmdlet debe modificar el estado en ejecución del sistema, no solo el estado del entorno de ejecución de Windows PowerShell. En estos casos, el cmdlet debe permitir al usuario confirmar si desea realizar el cambio o no.
Para admitir la confirmación de que un cmdlet debe hacer dos cosas.
Declare que el cmdlet admite la confirmación al especificar el atributo System.Management.Automation.CmdletAttribute estableciendo la palabra clave SupportsShouldProcess en
true
.Llame a System.Management.Automation.Cmdlet.ShouldProcess durante la ejecución del cmdlet (como se muestra en el ejemplo siguiente).
Al admitir la confirmación, un cmdlet expone los parámetros de Confirm
y WhatIf
proporcionados por Windows PowerShell y también cumple las directrices de desarrollo de cmdlets (para obtener más información sobre las directrices de desarrollo de cmdlets, vea Directrices de desarrollo de cmdlets.).
Cambiar el sistema
El acto de "cambiar el sistema" hace referencia a cualquier cmdlet que pueda cambiar el estado del sistema fuera de Windows PowerShell. Por ejemplo, detener un proceso, habilitar o deshabilitar una cuenta de usuario o agregar una fila a una tabla de base de datos son todos los cambios en el sistema que se deben confirmar.
Por el contrario, las operaciones que leen datos o establecen conexiones transitorias no cambian el sistema y, por lo general, no requieren confirmación. La confirmación tampoco es necesaria para las acciones cuyo efecto está limitado a dentro del entorno de ejecución de Windows PowerShell, como Set-Variable
. Los cmdlets que podrían o no realizar un cambio persistente deben declarar SupportsShouldProcess
y llamar a System.Management.Automation.Cmdlet.ShouldProcess solo si están a punto de realizar un cambio persistente.
Nota:
La confirmación shouldProcess solo se aplica a los cmdlets. Si un comando o script modifica el estado en ejecución de un sistema llamando directamente a propiedades o métodos de .NET, o llamando a aplicaciones fuera de Windows PowerShell, esta forma de confirmación no estará disponible.
The StopProc Cmdlet
En este tema se describe un cmdlet de Stop-Proc que intenta detener los procesos que se recuperan mediante el cmdlet Get-Proc (descrito en Creating Your First Cmdlet).
Definición del cmdlet
El primer paso en la creación de cmdlets siempre es asignar un nombre al cmdlet y declarar la clase .NET que implementa el cmdlet. Dado que está escribiendo un cmdlet para cambiar el sistema, debe denominarse en consecuencia. Este cmdlet detiene los procesos del sistema, por lo que el nombre del verbo elegido aquí es "Stop", definido por la clase System.Management.Automation.VerbsLifecycle, con el nombre "Proc" para indicar que el cmdlet detiene los procesos. Para obtener más información sobre los verbos de cmdlet aprobados, consulte Nombres de verbos de cmdlet.
A continuación se muestra la definición de clase para este cmdlet Stop-Proc.
[Cmdlet(VerbsLifecycle.Stop, "Proc",
SupportsShouldProcess = true)]
public class StopProcCommand : Cmdlet
Tenga en cuenta que en la declaración de System.Management.Automation.CmdletAttribute, la palabra clave del atributo SupportsShouldProcess
se establece en true
para permitir que el cmdlet realice llamadas a System.Management.Automation.Cmdlet.ShouldProcess y System.Management.Automation.Cmdlet.ShouldContinue.
Sin este conjunto de palabras clave, los parámetros Confirm
y WhatIf
no estarán disponibles para el usuario.
Acciones extremadamente destructivas
Algunas operaciones son extremadamente destructivas, como volver a formatear una partición de disco duro activa. En estos casos, el cmdlet debe establecer ConfirmImpact
= ConfirmImpact.High
al declarar el atributo System.Management.Automation.CmdletAttribute. Esta configuración obliga al cmdlet a solicitar confirmación del usuario incluso cuando el usuario no haya especificado el parámetro Confirm
. Sin embargo, los desarrolladores de cmdlets deben evitar el uso excesivo de ConfirmImpact
para las operaciones que solo son potencialmente destructivas, como eliminar una cuenta de usuario. Recuerde que si ConfirmImpact
está establecido en System.Management.Automation.ConfirmImpactHigh.
De forma similar, es poco probable que algunas operaciones sean destructivas, aunque en teoría modifican el estado en ejecución de un sistema fuera de Windows PowerShell. Estos cmdlets pueden establecer ConfirmImpact
en System.Management.Automation.ConfirmImpact.Low.
Esto omitirá las solicitudes de confirmación en las que el usuario ha pedido que confirme solo las operaciones de impacto medio y alto impacto.
Definición de parámetros para la modificación del sistema
En esta sección se describe cómo definir los parámetros del cmdlet, incluidos los necesarios para admitir la modificación del sistema. Consulte Agregar parámetros que procesan la entrada CommandLine si necesita información general sobre cómo definir parámetros.
El cmdlet Stop-Proc define tres parámetros: Name
, Force
y PassThru
.
El parámetro Name
corresponde a la propiedad Name
del objeto de entrada de proceso. Tenga en cuenta que el parámetro Name
de este ejemplo es obligatorio, ya que el cmdlet producirá un error si no tiene un proceso con nombre para detenerlo.
El parámetro Force
permite al usuario invalidar las llamadas a System.Management.Automation.Cmdlet.ShouldContinue.
De hecho, cualquier cmdlet que llame a System.Management.Automation.Cmdlet.ShouldContinue debe tener un parámetro Force
para que, cuando se especifique Force
, el cmdlet omite la llamada a System.Management.Automation.Cmdlet.ShouldContinue y continúa con la operación. Tenga en cuenta que esto no afecta a las llamadas a System.Management.Automation.Cmdlet.ShouldProcess.
El parámetro PassThru
permite al usuario indicar si el cmdlet pasa un objeto de salida a través de la canalización, en este caso, después de detener un proceso. Tenga en cuenta que este parámetro está vinculado al propio cmdlet en lugar de a una propiedad del objeto de entrada.
Esta es la declaración de parámetros del 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;
Invalidación de un método de procesamiento de entrada
El cmdlet debe invalidar un método de procesamiento de entrada. En el código siguiente se muestra la invalidación System.Management.Automation.Cmdlet.ProcessRecord usada en el cmdlet Stop-Proc de ejemplo. Para cada nombre de proceso solicitado, este método garantiza que el proceso no es un proceso especial, intenta detener el proceso y, a continuación, envía un objeto de salida si se especifica el parámetro 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
Llamar al método ShouldProcess
El método de procesamiento de entrada del cmdlet debe llamar al método System.Management.Automation.Cmdlet.ShouldProcess para confirmar la ejecución de una operación antes de que se realice un cambio (por ejemplo, eliminar archivos) al estado en ejecución del sistema. Esto permite que el entorno de ejecución de Windows PowerShell proporcione el comportamiento correcto de "WhatIf" y "Confirmar" dentro del shell.
Nota:
Si un cmdlet indica que admite debe procesarse y no puede realizar la llamada al System.Management.Automation.Cmdlet.ShouldProcess, el usuario podría modificar el sistema de forma inesperada.
La llamada a System.Management.Automation.Cmdlet.ShouldProcess envía el nombre del recurso que se va a cambiar al usuario, con el tiempo de ejecución de Windows PowerShell teniendo en cuenta cualquier configuración de línea de comandos o variables de preferencia para determinar lo que se debe mostrar al usuario.
En el ejemplo siguiente se muestra la llamada a System.Management.Automation.Cmdlet.ShouldProcess de la invalidación del método System.Management.Automation.Cmdlet.ProcessRecord en el cmdlet Stop-Proc de ejemplo.
if (!ShouldProcess(string.Format("{0} ({1})", processName,
process.Id)))
{
continue;
}
Llamar al método ShouldContinue
La llamada al método System.Management.Automation.Cmdlet.ShouldContinue envía un mensaje secundario al usuario. Esta llamada se realiza después de la llamada a System.Management.Automation.Cmdlet.ShouldProcess devuelve true
y si el parámetro Force
no se estableció en true
. A continuación, el usuario puede proporcionar comentarios para indicar si se debe continuar la operación. El cmdlet llama a System.Management.Automation.Cmdlet.ShouldContinue como comprobación adicional de modificaciones potencialmente peligrosas del sistema o cuando quiera proporcionar opciones sí a todos y no-to-all al usuario.
En el ejemplo siguiente se muestra la llamada a System.Management.Automation.Cmdlet.ShouldContinue de la invalidación del método System.Management.Automation.Cmdlet.ProcessRecord en el cmdlet Stop-Proc de ejemplo.
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...
Detener el procesamiento de entrada
El método de procesamiento de entrada de un cmdlet que realiza modificaciones del sistema debe proporcionar una manera de detener el procesamiento de la entrada. En el caso de este cmdlet de Stop-Proc, se realiza una llamada desde el método System.Management.Automation.Cmdlet.ProcessRecord al método System.Diagnostics.Process.Kill*. Dado que el parámetro PassThru
está establecido en true
, System.Management.Automation.Cmdlet.ProcessRecord también llama a system.Management.Automation.Cmdlet.WriteObject para enviar el objeto de proceso a la canalización.
Ejemplo de código
Para obtener el código de ejemplo de C# completo, vea Ejemplo StopProcessSample01.
Definición de tipos de objeto y formato
Windows PowerShell pasa información entre cmdlets mediante objetos .NET. Por lo tanto, es posible que un cmdlet tenga que definir su propio tipo o que el cmdlet tenga que extender un tipo existente proporcionado por otro cmdlet. Para obtener más información sobre cómo definir nuevos tipos o ampliar tipos existentes, vea Extensión de tipos de objeto y formato.
Compilación del cmdlet
Después de implementar un cmdlet, debe registrarse con Windows PowerShell a través de un complemento de Windows PowerShell. Para obtener más información sobre el registro de cmdlets, consulte Registro de cmdlets, proveedores y aplicaciones host.
Prueba del cmdlet
Cuando el cmdlet se haya registrado con Windows PowerShell, puede probarlo ejecutándolo en la línea de comandos. Estas son varias pruebas que prueban el cmdlet Stop-Proc. Para obtener más información sobre el uso de cmdlets desde la línea de comandos, consulte la Introducción a Windows PowerShell.
Inicie Windows PowerShell y use el cmdlet Stop-Proc para detener el procesamiento, como se muestra a continuación. Dado que el cmdlet especifica el parámetro
Name
como obligatorio, el cmdlet consulta el parámetro .PS> Stop-Proc
Aparece la salida siguiente.
Cmdlet Stop-Proc at command pipeline position 1 Supply values for the following parameters: Name[0]:
Ahora vamos a usar el cmdlet para detener el proceso denominado "NOTEPAD". El cmdlet le pide que confirme la acción.
PS> Stop-Proc -Name notepad
Aparece la salida siguiente.
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
Use Stop-Proc como se muestra para detener el proceso crítico denominado "WINLOGON". Se le pide y le advierte sobre cómo realizar esta acción porque hará que el sistema operativo se reinicie.
PS> Stop-Proc -Name Winlogon
Aparece la salida siguiente.
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
Ahora vamos a intentar detener el proceso WINLOGON sin recibir una advertencia. Tenga en cuenta que esta entrada de comando usa el parámetro
Force
para invalidar la advertencia.PS> Stop-Proc -Name winlogon -Force
Aparece la salida siguiente.
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
Véase también
agregar parámetros que procesan Command-Line entrada
extensión de tipos de objeto y formato