此範例示範如何撰寫 Cmdlet,以在使用者嘗試停止進程之前要求意見反應,以及如何實作 PassThru 參數,指出使用者想要 Cmdlet 傳回物件。 此 Cmdlet 類似於 Windows PowerShell 2.0 所提供的 Stop-Process Cmdlet。
如何使用 Visual Studio 建置範例
安裝 Windows PowerShell 2.0 SDK 後,流覽至 StopProcessSample01 資料夾。 預設位置為
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\WindowsPowerShell\csharp\StopProcessSample01。按兩下解決方案 (.sln) 檔案的圖示。 這會在 Visual Studio 中開啟範例專案Microsoft。
在 [建置] 功能表中,選取 [建置方案],以在預設
\bin或\bin\debug資料夾中建置範例的連結庫。
如何執行範例
建立下列模組資料夾:
[user]\Documents\WindowsPowerShell\Modules\StopProcessSample01將範例元件複製到模組資料夾。
啟動 Windows PowerShell。
執行下列命令,將元件載入 Windows PowerShell:
Import-Module stopprossessample01執行下列命令以執行 Cmdlet:
Stop-Proc
需求
此範例需要 Windows PowerShell 2.0。
演示
此範例示範下列專案。
使用 Cmdlet 屬性宣告 Cmdlet 類別。
使用 Parameter 屬性宣告 Cmdlet 參數。
呼叫 ShouldProcess 方法來要求確認。
實作
PassThru參數,指出使用者是否想要 Cmdlet 傳回物件。 根據預設,此 Cmdlet 不會將 對象傳回至管線。
範例
這個範例示範如何實作 PassThru 參數,指出使用者想要 Cmdlet 傳回物件,以及如何透過呼叫 ShouldProcess 和 ShouldContinue 方法來要求使用者意見反應。
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",
SupportsShouldProcess = true)]
public class StopProcCommand : Cmdlet
{
#region Parameters
/// <summary>
/// This parameter provides the list of process names on
/// which the Stop-Proc cmdlet will work.
/// </summary>
[Parameter(
Position = 0,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true
)]
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]
public SwitchParameter PassThru
{
get { return passThru; }
set { passThru = value; }
}
private bool passThru;
#endregion Parameters
#region Cmdlet Overrides
/// <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()
{
foreach (string name in processNames)
{
// For every process name passed to the cmdlet, get the associated
// processes.
// Write a non-terminating error for failure to retrieve
// a process.
Process[] processes;
try
{
processes = Process.GetProcessesByName(name);
}
catch (InvalidOperationException ioe)
{
WriteError(new ErrorRecord(ioe,"UnableToAccessProcessByName",
ErrorCategory.InvalidOperation, name));
continue;
}
// Try to stop the processes that have been retrieved.
foreach (Process process in processes)
{
string processName;
try
{
processName = process.ProcessName;
}
catch (Win32Exception e)
{
WriteError(new ErrorRecord(e, "ProcessNameNotFound",
ErrorCategory.ReadError, process));
continue;
}
// Confirm the operation with the user first.
// This is always false if the WhatIf parameter is set.
if (!ShouldProcess(string.Format(CultureInfo.CurrentCulture,"{0} ({1})", processName,
process.Id)))
{
continue;
}
// Make sure that the user really wants to stop a critical
// process that could possibly stop the computer.
bool criticalProcess =
criticalProcessNames.Contains(processName.ToLower(CultureInfo.CurrentCulture));
if (criticalProcess &&!force)
{
string 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))
{
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.
WriteError(new ErrorRecord(e, "CouldNotStopProcess",
ErrorCategory.CloseError, process));
continue;
} // if ((e is...
else throw;
} // catch
// If the PassThru parameter is
// specified, return the terminated process.
if (passThru)
{
WriteObject(process);
}
} // foreach (Process...
} // foreach (string...
} // ProcessRecord
#endregion Cmdlet Overrides
#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" }
);
#endregion Private Data
} // StopProcCommand
#endregion StopProcCommand
}