システムを変更するコマンドレットを作成する
場合によっては、コマンドレットは、ランタイムの状態ではなく、システムの実行状態Windows PowerShellがあります。 このような場合、コマンドレットを使用すると、ユーザーは変更を行うかどうかを確認できます。
確認をサポートするには、コマンドレットで 2 つのことを行う必要があります。
SupportsShouldProcess キーワードを に設定して System.Management.Automation.CmdletAttribute 属性を指定すると、コマンドレットで確認がサポートされます
true
。コマンドレット の実行中に System.Management.Automation.Cmdlet.ShouldProcess を呼び出します (次の例を参照)。
確認をサポートすることで、コマンドレットは Windows PowerShell によって提供される パラメーターと パラメーターを公開し、コマンドレットの開発ガイドラインも満たします (コマンドレットの開発ガイドラインの詳細については、「コマンドレット開発ガイドライン」を参照してください Confirm
WhatIf
)。
システムの変更
"システムを変更する" という行為は、システムの状態を変更する可能性のあるコマンドレットを指Windows PowerShell。 たとえば、プロセスの停止、ユーザー アカウントの有効化または無効化、データベース テーブルへの行の追加はすべて、確認する必要があるシステムに対する変更です。
これに対し、データを読み取る操作や一時的な接続を確立する操作では、システムは変更されません。通常、確認は必要ではありません。 また、その効果がランタイム内の に制限されているアクション (など) Windows PowerShell必要はありません set-variable
。 永続的な変更を行う場合と変更しない可能性があるコマンドレットは、永続的な変更を行う場合にのみ SupportsShouldProcess
、System.Management.Automation.Cmdlet.ShouldProcess を宣言して呼び出す必要があります。
注意
ShouldProcess の確認はコマンドレットにのみ適用されます。 コマンドまたはスクリプトが .NET のメソッドまたはプロパティを直接呼び出したり、Windows PowerShell の外部でアプリケーションを呼び出したりして、システムの実行状態を変更した場合、この形式の確認は使用できません。
StopProc コマンドレット
このトピックでは、Stop-Proc コマンドレットを使用して取得されたプロセスを停止しようとする Get-Proc コマンドレットについて説明します (「最初のコマンドレットの作成」を参照)。
コマンドレットの定義
コマンドレットの作成の最初の手順は、常にコマンドレットに名前を付け、コマンドレットを実装する .NET クラスを宣言します。 システムを変更するコマンドレットを作成する場合は、その名前を変更する必要があります。 このコマンドレットはシステム プロセスを停止します。そのため、ここで選択した動詞名は "Stop" です。これは System.Management.Automation.Verbslifecycle クラスで定義され、コマンドレットがプロセスを停止する名詞は "Proc" です。 承認されたコマンドレット動詞の詳細については、「コマンドレット動詞名」 を参照してください。
このコマンドレットのクラス定義を次Stop-Procします。
[Cmdlet(VerbsLifecycle.Stop, "Proc",
SupportsShouldProcess = true)]
public class StopProcCommand : Cmdlet
System.Management.Automation.CmdletAttribute宣言では、 属性キーワードが に設定され、コマンドレットが SupportsShouldProcess
true
System.Management.Automation.Cmdlet.ShouldProcessおよびSystem.Management.Automation.Cmdlet.ShouldContinueを呼び出すことができます。
このキーワードを設定しない場合、 Confirm
WhatIf
パラメーターと パラメーターはユーザーが使用できません。
非常に破壊的なアクション
一部の操作は、アクティブなハード ディスク パーティションの再フォーマットなど、非常に破壊的です。 このような場合は ConfirmImpact
= ConfirmImpact.High
、System.Management.Automation.CmdletAttribute属性を宣言するときに、 コマンドレットを設定する必要があります。 この設定により、ユーザーがパラメーターを指定していない場合でも、コマンドレットはユーザーの確認を要求 Confirm
します。 ただし、コマンドレット開発者は、ユーザー アカウントの削除など、破壊的である可能性がある操作の過剰使用 ConfirmImpact
を避ける必要があります。 が ConfirmImpact
System.Management.Automation.ConfirmImpactHigh に設定されている場合は 注意
してください。
同様に、一部の操作は破壊的になる可能性は低い一方で、理論的にはシステムの実行状態を外部のシステムに変更Windows PowerShell。 このようなコマンドレットは ConfirmImpact
、System.Management.Automation.Confirmimpact.Low に設定できます。
これにより、ユーザーが中程度の影響と影響の大きな操作のみを確認する必要がある確認要求はバイパスされます。
システム変更のパラメーターの定義
このセクションでは、システム変更をサポートするために必要なパラメーターを含め、コマンドレット パラメーターを定義する方法について説明します。 パラメーター の定義に関する一般的な情報が必要な 場合は、「コマンド ライン入力を処理するパラメーターの追加」を参照してください。
このStop-Proc、、および の 3 つの Name
パラメーター Force
を定義します PassThru
。
パラメーター Name
は、プロセス入力 Name
オブジェクトの プロパティに対応します。 コマンドレットに停止する名前付きプロセスが存在しない場合、コマンドレットは失敗しますので、このサンプルのパラメーターは必須 Name
です。
パラメーター Force
を使用すると、ユーザーは System.Management.Automation.Cmdlet.ShouldContinueの呼び出しをオーバーライドできます。
実際 、System.Management.Automation.Cmdlet.ShouldContinue を呼び出すコマンドレットには パラメーターが必要です。このパラメーターを指定すると、コマンドレットは Force
Force
System.Management.Automation.Cmdlet.ShouldContinue の呼び出しをスキップし、操作を続行します。 これはSystem.Management.Automation.Cmdlet.ShouldProcess の呼び出しには影響しません。
パラメーターを使用すると、プロセスが停止した後にコマンドレットがパイプラインを介して出力オブジェクトを渡すかどうかをユーザー PassThru
が指定できます。 このパラメーターは、入力オブジェクトの プロパティではなく、コマンドレット自体に関連付けられている点に注意してください。
次に示すのは、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;
入力処理メソッドのオーバーライド
コマンドレットは、入力処理メソッドをオーバーライドする必要があります。 次のコードは、サンプルコマンドレットで使用される System.Management.Automation.Cmdlet.ProcessRecord オーバーライドをStop-Procしています。 要求されたプロセス名ごとに、このメソッドは、プロセスが特別なプロセスではなかからず、プロセスの停止を試み、パラメーターが指定されている場合は出力オブジェクトを 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
ShouldProcess メソッドの呼び出し
コマンドレットの入力処理メソッドは 、System.Management.Automation.Cmdlet.ShouldProcess メソッドを呼び出して、変更 (ファイルの削除など) がシステムの実行状態に加わる前に操作の実行を確認する必要があります。 これにより、Windows PowerShellランタイムは、シェル内で正しい "WhatIf" と "Confirm" の動作を指定できます。
注意
をサポートするコマンドレットが を処理する必要があるという状態で System.Management.Automation.Cmdlet.ShouldProcess 呼び出しを実行できない場合、ユーザーはシステムを予期せず変更する可能性があります。
System.Management.Automation.Cmdlet.ShouldProcessの呼び出しは、変更するリソースの名前をユーザーに送信します。Windows PowerShell ランタイムでは、ユーザーに表示する必要がある操作を決定する際に、コマンド ライン設定またはユーザー設定変数が考慮されます。
次の例は、サンプル Stop-Proc コマンドレットのSystem.Management.Automation.Cmdlet.ProcessRecordメソッドのオーバーライドからのSystem.Management.Automation.Cmdlet.ShouldProcessの呼び出しを示しています。
if (!ShouldProcess(string.Format("{0} ({1})", processName,
process.Id)))
{
continue;
}
ShouldContinue メソッドの呼び出し
System.Management.Automation.Cmdlet.ShouldContinueメソッドの呼び出しは、ユーザーにセカンダリ メッセージを送信します。 この呼び出しは 、System.Management.Automation.Cmdlet.ShouldProcess の呼び出しが返された後、および パラメーターが に設定されていない場合 true
Force
に行います true
。 ユーザーは、操作を継続する必要があるかどうかを示すフィードバックを提供できます。 コマンドレットは 、System.Management.Automation.Cmdlet.ShouldContinue を呼び出して、危険な可能性のあるシステム変更の追加チェックとして、またはユーザーに対して "はい" オプションと "すべてなし" オプションを指定する場合に呼び出します。
次の例は、サンプル Stop-Proc コマンドレットのSystem.Management.Automation.Cmdlet.ProcessRecordメソッドのオーバーライドからのSystem.Management.Automation.Cmdlet.ShouldContinueの呼び出しを示しています。
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-Proc コマンドレットの場合 、System.Management.Automation.Cmdlet.ProcessRecord メソッドから System.Diagnostics.Process.Kill* メソッドへの呼び出しが行います。 パラメーターが に設定されている場合 PassThru
true
、System.Management.Automation.Cmdlet.ProcessRecord は System.Management.Automation.Cmdlet.WriteObject も呼び出して、プロセス オブジェクトをパイプラインに送信します。
コード サンプル
完全な C# サンプル コードについては 、「StopProcessSample01 サンプル」を参照してください。
オブジェクト型と書式設定の定義
Windows PowerShell.Net オブジェクトを使用してコマンドレット間で情報を渡します。 そのため、コマンドレットで独自の型を定義する必要がある場合や、別のコマンドレットによって提供される既存の型を拡張する必要がある場合があります。 新しい型の定義または既存の型の拡張の詳細については、「オブジェクト型の拡張」および「書式設定」 を参照してください。
コマンドレットの構築
コマンドレットを実装した後、 スナップインを使用してWindows PowerShellに登録Windows PowerShell必要があります。 コマンドレットの登録の詳細については、「コマンドレット、プロバイダー、およびホスト アプリケーションを登録する方法」 を参照してください。
コマンドレットのテスト
コマンドレットが Windows PowerShellに登録されている場合は、コマンド ラインで実行してテストできます。 次に示すのは、このコマンドレットをテストするStop-Procです。 コマンド ラインからコマンドレットを使用する方法の詳細については、「 コマンド ラインを使用したはじめにをWindows PowerShell。
次Windows PowerShellを開始し、Stop-Proc コマンドレットを使用して処理を停止します。 コマンドレットはパラメーターを必須として指定します。そのため、コマンドレットは パラメーター
Name
を照会します。PS> stop-proc
次のような出力が表示されます。
Cmdlet stop-proc at command pipeline position 1 Supply values for the following parameters: Name[0]:
次に、 コマンドレットを使用して、"NOTEPAD" という名前のプロセスを停止します。 コマンドレットは、アクションの確認を求めるメッセージを表示します。
PS> stop-proc -Name notepad
次のような出力が表示されます。
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
次Stop-Procを使用して、"WINLOGON" という名前の重要なプロセスを停止します。 オペレーティング システムが再起動する原因となるので、この操作の実行を求め、警告が表示されます。
PS> stop-proc -Name Winlogon
次のような出力が表示されます。
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
次に、警告を受け取らずに WINLOGON プロセスを停止します。 このコマンド エントリでは、 パラメーターを使用して
Force
警告がオーバーライドされます。PS> stop-proc -Name winlogon -Force
次のような出力が表示されます。
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