次の方法で共有


システムを変更するコマンドレットを作成する

場合によっては、Windows PowerShell ランタイムの状態だけでなく、コマンドレットでシステムの実行状態を変更する必要があります。 このような場合、コマンドレットはユーザーが変更を行うかどうかを確認できるようにする必要があります。

確認をサポートするには、コマンドレットで 2 つの操作を行う必要があります。

確認をサポートすることで、コマンドレットは、Windows PowerShell によって提供される Confirm パラメーターと WhatIf パラメーターを公開し、コマンドレットの開発ガイドラインも満たします (コマンドレット開発ガイドラインの詳細については、「コマンドレット開発ガイドライン を参照してください)。

システムの変更

"システムを変更する" という動作は、Windows PowerShell の外部でシステムの状態を変更する可能性のあるコマンドレットを指します。 たとえば、プロセスの停止、ユーザー アカウントの有効化または無効化、データベース テーブルへの行の追加は、確認する必要があるシステムに対するすべての変更です。 これに対し、データを読み取ったり、一時的な接続を確立したりする操作はシステムを変更せず、通常は確認を必要としません。 Set-Variableなど、Windows PowerShell ランタイム内に限定された効果を持つアクションについても確認は必要ありません。 永続的な変更を行う可能性があるコマンドレットとそうでないコマンドレットでは、SupportsShouldProcess を宣言し、System.Management.Automation.Cmdlet.ShouldProcess 、永続的な変更を加える場合にのみ呼び出す必要があります。

ShouldProcess の確認はコマンドレットにのみ適用されます。 .NET のメソッドまたはプロパティを直接呼び出すか、Windows PowerShell の外部でアプリケーションを呼び出すことによって、コマンドまたはスクリプトによってシステムの実行状態が変更された場合、この形式の確認は使用できません。

StopProc コマンドレット

このトピックでは、Get-Proc コマンドレットを使用して取得されたプロセスを停止しようとする Stop-Proc コマンドレットについて説明します (「最初のコマンドレット の作成」を参照してください)。

コマンドレットの定義

コマンドレットの作成の最初の手順は、常にコマンドレットに名前を付け、コマンドレットを実装する .NET クラスを宣言することです。 システムを変更するコマンドレットを記述しているため、それに応じて名前を付ける必要があります。 このコマンドレットはシステム プロセスを停止するため、ここで選択した動詞名は、System.Management.Automation.VerbsLifecycle クラスによって定義される "Stop" で、コマンドレットがプロセスを停止することを示す名詞 "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 パラメーターをユーザーが使用できなくなります。

非常に破壊的なアクション

一部の操作は、アクティブなハード ディスク パーティションの再フォーマットなど、非常に破壊的です。 このような場合、System.Management.Automation.CmdletAttribute 属性を宣言するときに、コマンドレット ConfirmImpact = ConfirmImpact.High を設定する必要があります。 この設定により、ユーザーが Confirm パラメーターを指定していない場合でも、コマンドレットはユーザーの確認を要求します。 ただし、コマンドレット開発者は、ユーザー アカウントの削除など、破壊的な可能性がある操作に ConfirmImpact を過剰に使用しないようにする必要があります。 ConfirmImpact が System.Management.Automation.ConfirmImpact Highに設定されている場合は注意してください。

同様に、一部の操作は破壊的な可能性はほとんどありませんが、理論上は Windows PowerShell の外部にあるシステムの実行状態を変更します。 このようなコマンドレットでは、ConfirmImpact を System.Management.Automation.ConfirmImpact.Low に設定できます。 これにより、ユーザーが中程度の影響と影響の大きい操作のみを確認するように求められた確認要求がバイパスされます。

システム変更のパラメーターの定義

このセクションでは、システムの変更をサポートするために必要なものも含めて、コマンドレット パラメーターを定義する方法について説明します。 パラメーターの定義に関する一般的な情報が必要な場合は、「コマンド ライン入力 を処理するパラメーターの追加」を参照してください。

Stop-Proc コマンドレットは、NameForce、および PassThruの 3 つのパラメーターを定義します。

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;

入力処理メソッドのオーバーライド

コマンドレットは、入力処理メソッドをオーバーライドする必要があります。 次のコードは、サンプル Stop-Proc コマンドレットで使用 System.Management.Automation.Cmdlet.ProcessRecord オーバーライドを示しています。 要求された各プロセス名に対して、このメソッドはプロセスが特殊なプロセスでないことを確認し、プロセスの停止を試み、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.Should Process 呼び出しを処理する必要があると示され、失敗した場合、ユーザーは予期せずシステムを変更する可能性があります。

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.ShouldProcesstrue を返した後、および Force パラメーターが trueに設定されていない場合に行われます。 ユーザーは、操作を続行する必要があるかどうかを示すフィードバックを提供できます。 このコマンドレットは、潜在的に危険なシステム変更の追加チェックとして、またはユーザーに yes-to-all オプションと no-to-all オプションを提供する場合に、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
    

こちらもご覧ください

入力 を処理するパラメーター Command-Line 追加する

オブジェクト型の拡張と書式設定

コマンドレット、プロバイダー、およびホスト アプリケーションを登録する方法

Windows PowerShell SDK の

コマンドレットのサンプル