StopProcessSample04 示例
此示例演示如何编写声明参数集、指定默认参数集以及可接受输入对象的 cmdlet。 此 cmdlet 类似于 Stop-Process
2.0 Windows PowerShell cmdlet。
如何使用示例生成Visual Studio。
安装 Windows PowerShell 2.0 SDK 后,导航到 StopProcessSample04 文件夹。 默认位置为 C:\Program Files (x86) \Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\WindowsPowerShell\csharp\StopProcessSample04。
双击解决方案 (.sln) 图标。 这会在 Microsoft Visual Studio 中打开示例项目。
在“生成”菜单中选择“生成解决方案” 。
示例的库将构建在默认的 \bin 或 \bin\debug 文件夹中。
如何运行示例
创建以下模块文件夹:
[user]/documents/windowspowershell/modules/StopProcessSample04
将示例程序集复制到 module 文件夹。
启动 Windows PowerShell。
运行以下命令,将程序集加载到Windows PowerShell:
import-module stopprossessample04
运行以下命令以运行 cmdlet:
stop-proc
要求
此示例需要 Windows PowerShell 2.0。
演示
此示例演示了以下内容。
使用 Cmdlet 属性声明 cmdlet 类。
使用 Parameter 属性声明 cmdlet 参数。
添加接受输入对象的参数。
向参数集添加参数
指定默认参数集。
示例
下面的代码演示了 Stop-Proc cmdlet 的实现,该 cmdlet 声明参数集、指定默认参数集,并可接受输入对象。
此示例演示输入对象、如何声明参数集,以及如何指定使用的默认参数集。
using System;
using System.Diagnostics;
using System.Collections;
using Win32Exception = System.ComponentModel.Win32Exception;
using System.Management.Automation; //Windows PowerShell namespace
using System.Globalization;
namespace Microsoft.Samples.PowerShell.Commands
{
#region StopProcCommand
/// <summary>
/// This class implements the stop-proc cmdlet.
/// </summary>
[Cmdlet(VerbsLifecycle.Stop, "Proc",
DefaultParameterSetName = "ProcessId",
SupportsShouldProcess = true)]
public class StopProcCommand : PSCmdlet
{
#region Parameters
/// <summary>
/// This parameter provides the list of process names on
/// which the Stop-Proc cmdlet will work.
/// </summary>
[Parameter(
Position = 0,
ParameterSetName = "ProcessName",
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
HelpMessage = "The name of one or more processes to stop. Wildcards are permitted."
)]
[Alias("ProcessName")]
public string[] Name
{
get { return processNames; }
set { processNames = value; }
}
private string[] processNames;
/// <summary>
/// This parameter overrides the ShouldContinue call to force
/// the cmdlet to stop its operation. This parameter should always
/// be used with caution.
/// </summary>
[Parameter]
public SwitchParameter Force
{
get { return force; }
set { force = value; }
}
private bool force;
/// <summary>
/// This parameter indicates that the cmdlet should return
/// an object to the pipeline after the processing has been
/// completed.
/// </summary>
[Parameter(
HelpMessage = "If set the process(es) will be passed to the pipeline after stopped."
)]
public SwitchParameter PassThru
{
get { return passThru; }
set { passThru = value; }
}
private bool passThru;
/// This parameter provides the list of process identifiers on
/// which the Stop-Proc cmdlet will work.
[Parameter(
ParameterSetName = "ProcessId",
Mandatory = true,
ValueFromPipelineByPropertyName = true,
ValueFromPipeline = true
)]
[Alias("ProcessId")]
public int[] Id
{
get { return processIds; }
set { processIds = value; }
}
private int[] processIds;
/// <summary>
/// This parameter accepts an array of Process objects from the
/// the pipeline. This object contains the processes to stop.
/// </summary>
/// <value>Process objects</value>
[Parameter(
ParameterSetName = "InputObject",
Mandatory = true,
ValueFromPipeline = true)]
public Process[] InputObject
{
get { return inputObject; }
set { inputObject = value; }
}
private Process[] inputObject;
#endregion Parameters
#region CmdletOverrides
/// <summary>
/// The ProcessRecord method does the following for each of the
/// requested process names:
/// 1) Check that the process is not a critical process.
/// 2) Attempt to stop that process.
/// If no process is requested then nothing occurs.
/// </summary>
protected override void ProcessRecord()
{
switch (ParameterSetName)
{
case "ProcessName":
ProcessByName();
break;
case "ProcessId":
ProcessById();
break;
case "InputObject":
foreach (Process process in inputObject)
{
SafeStopProcess(process);
}
break;
default:
throw new ArgumentException("Bad ParameterSet Name");
} // switch (ParameterSetName...
} // ProcessRecord
#endregion Cmdlet Overrides
#region Helper Methods
/// <summary>
/// Returns all processes with matching names.
/// </summary>
/// <param name="processName">
/// The name of the processes to return.
/// </param>
/// <param name="allProcesses">An array of all
/// computer processes.</param>
/// <returns>An array of matching processes.</returns>
internal ArrayList SafeGetProcessesByName(string processName,
ref ArrayList allProcesses)
{
// Create and array to store the matching processes.
ArrayList matchingProcesses = new ArrayList();
// Create the wildcard for pattern matching.
WildcardOptions options = WildcardOptions.IgnoreCase |
WildcardOptions.Compiled;
WildcardPattern wildcard = new WildcardPattern(processName, options);
// Walk all of the machine processes.
foreach(Process process in allProcesses)
{
string processNameToMatch = null;
try
{
processNameToMatch = process.ProcessName;
}
catch (Win32Exception e)
{
// Remove the process from the list so that it is not
// checked again.
allProcesses.Remove(process);
string message =
String.Format(CultureInfo.CurrentCulture, "The process \"{0}\" could not be found",
processName);
WriteVerbose(message);
WriteError(new ErrorRecord(e, "ProcessNotFound",
ErrorCategory.ObjectNotFound, processName));
continue;
}
if (!wildcard.IsMatch(processNameToMatch))
{
continue;
}
matchingProcesses.Add(process);
} // foreach(Process...
return matchingProcesses;
} // SafeGetProcessesByName
/// <summary>
/// Safely stops a named process. Used as standalone function
/// to declutter the ProcessRecord method.
/// </summary>
/// <param name="process">The process to stop.</param>
private void SafeStopProcess(Process process)
{
string processName = null;
try
{
processName = process.ProcessName;
}
catch (Win32Exception e)
{
WriteError(new ErrorRecord(e, "ProcessNotFound",
ErrorCategory.OpenError, processName));
return;
}
// Confirm the operation first.
// This is always false if the WhatIf parameter is specified.
if (!ShouldProcess(string.Format(CultureInfo.CurrentCulture,
"{0} ({1})", processName, process.Id)))
{
return;
}
// Make sure that the user really wants to stop a critical
// process that can possibly stop the computer.
bool criticalProcess = criticalProcessNames.Contains(processName.ToLower(CultureInfo.CurrentCulture));
string message = null;
if (criticalProcess && !force)
{
message = String.Format(CultureInfo.CurrentCulture,
"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 the ProcessRecord method is called
// multiple times when objects are received as inputs from
// the pipeline. So to retain YesToAll and NoToAll input that
// the user may enter across multiple calls to this function,
// they are stored as private members of the cmdlet.
if (!ShouldContinue(message, "Warning!",
ref yesToAll, ref noToAll))
{
return;
}
} // if (criticalProcess...
// Display a warning message if stopping a critical
// process.
if (criticalProcess)
{
message =
String.Format(CultureInfo.CurrentCulture,
"Stopping the critical process \"{0}\".",
processName);
WriteWarning(message);
} // if (criticalProcess...
try
{
// Stop the process.
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.
WriteError(new ErrorRecord(e, "CouldNotStopProcess",
ErrorCategory.CloseError,
process)
);
return;
} // if ((e is...
else throw;
} // catch
// Write a user-level verbose message to the pipeline. These are
// intended to give the user detailed information on the
// operations performed by the cmdlet. These messages will
// appear with the -Verbose option.
message = String.Format(CultureInfo.CurrentCulture,
"Stopped process \"{0}\", pid {1}.",
processName, process.Id);
WriteVerbose(message);
// If the PassThru parameter is specified, return the terminated
// process to the pipeline.
if (passThru)
{
// Write a debug message to the host that can be used
// when troubleshooting a problem. All debug messages
// will appear with the -Debug option
message =
String.Format(CultureInfo.CurrentCulture,
"Writing process \"{0}\" to pipeline",
processName);
WriteDebug(message);
WriteObject(process);
} // if (passThru..
} // SafeStopProcess
/// <summary>
/// Stop processes based on their names (using the
/// ParameterSetName as ProcessName)
/// </summary>
private void ProcessByName()
{
ArrayList allProcesses = null;
// Get a list of all processes.
try
{
allProcesses = new ArrayList(Process.GetProcesses());
}
catch (InvalidOperationException ioe)
{
base.ThrowTerminatingError(new ErrorRecord(
ioe, "UnableToAccessProcessList",
ErrorCategory.InvalidOperation, null));
}
// If a process name is passed to the cmdlet, get
// the associated processes.
// Write a nonterminating error for failure to
// retrieve a process.
foreach (string name in processNames)
{
// The allProcesses array list is passed as a reference because
// any process whose name cannot be obtained will be removed
// from the list so that its not compared the next time.
ArrayList processes =
SafeGetProcessesByName(name, ref allProcesses);
// If no processes were found write a non-
// terminating error.
if (processes.Count == 0)
{
WriteError(new ErrorRecord(
new Exception("Process not found."),
"ProcessNotFound",
ErrorCategory.ObjectNotFound,
name));
} // if (processes...
// Otherwise terminate all processes in the list.
else
{
foreach (Process process in processes)
{
SafeStopProcess(process);
} // foreach (Process...
} // else
} // foreach (string...
} // ProcessByName
/// <summary>
/// Stop processes based on their identifiers (using the
/// ParameterSetName as ProcessIds)
/// </summary>
internal void ProcessById()
{
foreach (int processId in processIds)
{
Process process = null;
try
{
process = Process.GetProcessById(processId);
// Write a debug message to the host that can be used
// when troubleshooting a problem. All debug messages
// will appear with the -Debug option
string message =
String.Format(CultureInfo.CurrentCulture,
"Acquired process for pid : {0}",
process.Id);
WriteDebug(message);
}
catch (ArgumentException ae)
{
string
message = String.Format(CultureInfo.CurrentCulture,
"The process id {0} could not be found",
processId);
WriteVerbose(message);
WriteError(new ErrorRecord(ae, "ProcessIdNotFound",
ErrorCategory.ObjectNotFound, processId));
continue;
}
SafeStopProcess(process);
} // foreach (int...
} // ProcessById
#endregion Helper Methods
#region Private Data
private bool yesToAll, noToAll;
/// <summary>
/// Partial list of critical processes that should not be
/// stopped. Lower case is used for case insensitive matching.
/// </summary>
private ArrayList criticalProcessNames = new ArrayList(
new string[] { "system", "winlogon", "spoolsv", "calc" }
);
#endregion Private Data
} // StopProcCommand
#endregion StopProcCommand
}