Share via


MSBuild プロジェクト ファイルから Windows PowerShell スクリプトを実行する

作成者: Jason Lee

このトピックでは、ビルドおよびデプロイ プロセスの一部としてWindows PowerShell スクリプトを実行する方法について説明します。 スクリプトは、ローカル (つまり、ビルド サーバー) で実行することも、移行先の Web サーバーやデータベース サーバーのようにリモートで実行することもできます。

デプロイ後のWindows PowerShell スクリプトを実行する理由は多数あります。 たとえば、次の操作を行います。

  • カスタム イベント ソースをレジストリに追加します。
  • アップロード用のファイル システム ディレクトリを生成します。
  • ビルド ディレクトリをクリーンアップします。
  • エントリをカスタム ログ ファイルに書き込みます。
  • 新しくプロビジョニングされた Web アプリケーションにユーザーを招待するメールを送信します。
  • 適切なアクセス許可を持つユーザー アカウントを作成します。
  • SQL Server インスタンス間のレプリケーションを構成します。

このトピックでは、Microsoft Build Engine (MSBuild) プロジェクト ファイル内のカスタム ターゲットからローカルとリモートの両方でWindows PowerShell スクリプトを実行する方法について説明します。

このトピックは、Fabrikam, Inc という架空の会社のエンタープライズ展開要件に基づく一連のチュートリアルの一部です。このチュートリアル シリーズでは、サンプル ソリューションである Contact Manager ソリューションを使用して、ASP.NET MVC 3 アプリケーション、Windows Communication Foundation (WCF) サービス、データベース プロジェクトなど、現実的なレベルの複雑さの Web アプリケーションを表します。

これらのチュートリアルの中心にある配置方法は、「 プロジェクト ファイルの理解」で説明されている分割プロジェクト ファイルのアプローチに基づいています。このアプローチでは、ビルド プロセスは 2 つのプロジェクト ファイルによって制御されます。1 つは、すべての移行先環境に適用されるビルド命令を含み、もう 1 つは環境固有のビルドと配置設定を含みます。 ビルド時に、環境固有のプロジェクト ファイルが環境に依存しないプロジェクト ファイルにマージされ、ビルド手順の完全なセットが形成されます。

タスクの概要

自動またはシングルステップのデプロイ プロセスの一部としてWindows PowerShell スクリプトを実行するには、次の大まかなタスクを完了する必要があります。

  • Windows PowerShell スクリプトをソリューションとソース管理に追加します。
  • Windows PowerShell スクリプトを呼び出すコマンドを作成します。
  • コマンド内の予約済み XML 文字をエスケープします。
  • カスタム MSBuild プロジェクト ファイルにターゲットを作成し、 Exec タスクを使用してコマンドを実行します。

このトピックでは、これらの手順を実行する方法について説明します。 このトピックのタスクとチュートリアルでは、MSBuild のターゲットとプロパティについて既に理解していることと、カスタム MSBuild プロジェクト ファイルを使用してビルドと配置プロセスを実行する方法を理解していることを前提としています。 詳細については、「 プロジェクト ファイルについて 」および「 ビルド プロセスについて」を参照してください。

Windows PowerShell スクリプトの作成と追加

このトピックのタスクでは、LogDeploy.ps1という名前のサンプル Windows PowerShell スクリプトを使用して、MSBuild からスクリプトを実行する方法を説明します。 LogDeploy.ps1 スクリプトには、1 行のエントリをログ ファイルに書き込む単純な関数が含まれています。

function LogDeployment
{
  param([string]$filepath,[string]$deployDestination)
  $datetime = Get-Date
  $filetext = "Deployed package to " + $deployDestination + " on " + $datetime
  $filetext | Out-File -filepath $filepath -Append
}

LogDeployment $args[0] $args[1]

LogDeploy.ps1 スクリプトは、2 つのパラメーターを受け入れます。 最初のパラメーターは、エントリを追加するログ ファイルへの完全なパスを表し、2 番目のパラメーターは、ログ ファイルに記録するデプロイ先を表します。 スクリプトを実行すると、次の形式でログ ファイルに行が追加されます。

Deployed package to TESTWEB1 on 02/11/2012 09:28:18

MSBuild でLogDeploy.ps1 スクリプトを使用できるようにするには、次の手順を実行する必要があります。

  • スクリプトをソース管理に追加します。
  • Visual Studio 2010 でソリューションにスクリプトを追加します。

ビルド サーバーとリモート コンピューターのどちらでスクリプトを実行する予定であるかに関係なく、ソリューション コンテンツを含むスクリプトを展開する必要はありません。 1 つのオプションは、ソリューション フォルダーにスクリプトを追加することです。 Contact Manager の例では、展開プロセスの一部として Windows PowerShell スクリプトを使用するため、スクリプトを [ソリューションの発行] フォルダーに追加するのが理にかなっています。

Contact Manager の例では、展開プロセスの一部として Windows PowerShell スクリプトを使用するため、スクリプトを [ソリューションの発行] フォルダーに追加するのが理にかなっています。

ソリューション フォルダーの内容は、ソース マテリアルとしてサーバーをビルドするためにコピーされます。 ただし、プロジェクト出力の一部は形成されません。

ビルド サーバーでのWindows PowerShell スクリプトの実行

一部のシナリオでは、プロジェクトをビルドするコンピューターでWindows PowerShellスクリプトを実行できます。 たとえば、Windows PowerShell スクリプトを使用してビルド フォルダーをクリーンしたり、カスタム ログ ファイルにエントリを書き込んだりできます。

構文については、MSBuild プロジェクト ファイルからWindows PowerShell スクリプトを実行することは、通常のコマンド プロンプトからWindows PowerShell スクリプトを実行する場合と同じです。 powershell.exe 実行可能ファイルを呼び出し、–command スイッチを使用して、Windows PowerShell実行するコマンドを指定する必要があります。 (Windows PowerShell v2 では、–file スイッチを使用することもできます)。 コマンドは、次の形式にする必要があります。

powershell.exe –command "& { [Path to script] 'parameter1' 'parameter2' ... }"

例:

powershell.exe –command 
  "& { C:\LogDeploy.ps1 'C:\DeployLogs\log.txt' 'TESTWEB1' }"

スクリプトへのパスにスペースが含まれている場合は、アンパサンドの前にファイル パスを単一引用符で囲む必要があります。 コマンドを囲むのに二重引用符を既に使用しているため、二重引用符を使用することはできません。

powershell.exe –command 
  "& { &'C:\Path With Spaces\LogDeploy.ps1' 
        'C:\Path With Spaces\log.txt' 
        'TESTWEB1' }"

MSBuild からこのコマンドを呼び出すときには、いくつかの追加の考慮事項があります。 まず、スクリプトが静かに実行されるように 、–NonInteractive フラグを含める必要があります。 次に、 –ExecutionPolicy フラグを適切な引数値と共に含める必要があります。 これにより、スクリプトに適用Windows PowerShell実行ポリシーを指定し、既定の実行ポリシーをオーバーライドできます。これにより、スクリプトの実行が妨げられる可能性があります。 次の引数値から選択できます。

  • [無制限] の値を指定すると、スクリプトが署名されているかどうかに関係なく、Windows PowerShellでスクリプトを実行できます。
  • RemoteSigned の値を指定すると、Windows PowerShellはローカル コンピューターで作成された署名されていないスクリプトを実行できます。 ただし、他の場所で作成されたスクリプトは署名する必要があります。 (実際には、ビルド サーバー上でローカルにWindows PowerShell スクリプトを作成した可能性は非常に低いです)。
  • AllSigned の値を指定すると、Windows PowerShellは署名付きスクリプトのみを実行できます。

既定の実行ポリシーは Restricted です。これにより、Windows PowerShellがスクリプト ファイルを実行できなくなります。

最後に、Windows PowerShell コマンドで発生する予約済み XML 文字をエスケープする必要があります。

  • 単一引用符を &apos に置き換えます。

  • 二重引用符を " に置き換えます。

  • アンパサンドを & に置き換えます。

  • これらの変更を行うと、コマンドは次のようになります。

powershell.exe –NonInteractive –ExecutionPolicy Unrestricted 
               –command "& { &'[Path to script]' 
                        '[parameter1]' 
                        '[parameter2]' } "

カスタム MSBuild プロジェクト ファイル内で、新しいターゲットを作成し、 Exec タスクを使用して次のコマンドを実行できます。

<Target Name="WriteLogEntry" Condition=" '$(WriteLogEntry)'!='false' ">
  <PropertyGroup>
    <PowerShellExe Condition=" '$(PowerShellExe)'=='' "> 
      %WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe
    </PowerShellExe>
    <ScriptLocation Condition=" '$(ScriptLocation)'=='' ">
      C:\Path With Spaces\LogDeploy.ps1
    </ScriptLocation>
    <LogFileLocation Condition=" '$(LogFileLocation)'=='' ">
      C:\Path With Spaces\ContactManagerDeployLog.txt
    </LogFileLocation>
  </PropertyGroup>
  <Exec Command="$(PowerShellExe) -NonInteractive -executionpolicy Unrestricted 
                 -command &quot;&amp; { 
                          &amp;&apos;$(ScriptLocation)&apos; 
                          &apos;$(LogFileLocation)&apos; 
                          &apos;$(MSDeployComputerName)&apos;} &quot;" />
</Target>

この例では、次の点に注意してください。

  • パラメーター値やWindows PowerShell実行可能ファイルの場所などの変数は、MSBuild プロパティとして宣言されます。
  • ユーザーがコマンド ラインからこれらの値をオーバーライドできるようにするための条件が含まれています。
  • MSDeployComputerName プロパティは、プロジェクト ファイル内の別の場所で宣言されています。

ビルド プロセスの一部としてこのターゲットを実行すると、Windows PowerShellコマンドが実行され、指定したファイルにログ エントリが書き込まれます。

リモート コンピューターでのWindows PowerShell スクリプトの実行

Windows PowerShellは、Windows リモート管理 (WinRM) を使用してリモート コンピューターでスクリプトを実行できます。 これを行うには、 Invoke-Command コマンドレットを使用する必要があります。 これにより、スクリプトをリモート コンピューターにコピーせずに、1 つ以上のリモート コンピューターに対してスクリプトを実行できます。 スクリプトの実行元のローカル コンピューターに結果が返されます。

注意

Invoke-Command コマンドレットを使用してリモート コンピューターでWindows PowerShell スクリプトを実行する前に、リモート メッセージを受け入れるように WinRM リスナーを構成する必要があります。 これを行うには、リモート コンピューターで コマンド winrm quickconfig を実行します。 詳細については、「 Windows リモート管理のインストールと構成」を参照してください。

Windows PowerShell ウィンドウから、次の構文を使用して、リモート コンピューターで LogDeploy.ps1 スクリプトを実行します。

Invoke-Command –ComputerName 'REMOTESERVER1' 
               –ScriptBlock { &"C:\Path With Spaces\LogDeploy.ps1"
                               'C:\Path With Spaces\Log.txt'
                               'TESTWEB1' }

注意

Invoke-Command を使用してスクリプト ファイルを実行する方法は他にもいくつかありますが、この方法は、パラメーター値を指定し、スペースを含むパスを管理する必要がある場合に最も簡単です。

コマンド プロンプトからこれを実行する場合は、Windows PowerShell実行可能ファイルを呼び出し、–command パラメーターを使用して手順を指定する必要があります。

powershell.exe –command 
  "& {Invoke-Command –ComputerName 'REMOTESERVER1' 
                     –ScriptBlock { &'C:\Path With Spaces\LogDeploy.ps1'
                                     'C:\Path With Spaces\Log.txt'
                                     'TESTWEB1' } "

前と同様に、MSBuild からコマンドを実行するときに、いくつかの追加のスイッチを指定し、予約済みの XML 文字をエスケープする必要があります。

powershell.exe -NonInteractive -executionpolicy Unrestricted 
               -command &quot;&amp; Invoke-Command 
                 –ComputerName &apos;REMOTESERVER1&apos;
                 -ScriptBlock { &amp;&apos;C:\Path With Spaces\LogDeploy.ps1&apos; 
                                &apos; C:\Path With Spaces\Log.txt &apos;  
                                &apos;TESTWEB1&apos; } &quot;

最後に、前と同様に、カスタム MSBuild ターゲット内で Exec タスクを使用してコマンドを実行できます。

<Target Name="WriteLogEntry" Condition=" '$(WriteLogEntry)'!='false' ">
  <PropertyGroup>
    <PowerShellExe Condition=" '$(PowerShellExe)'=='' "> 
      %WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe
    </PowerShellExe>
    <ScriptLocation Condition=" '$(ScriptLocation)'=='' ">
      C:\Path With Spaces\LogDeploy.ps1
    </ScriptLocation>
    <LogFileLocation Condition=" '$(LogFileLocation)'=='' ">
      C:\Path With Spaces\ContactManagerDeployLog.txt
    </LogFileLocation>
  </PropertyGroup>
  <Exec Command="$(PowerShellExe) -NonInteractive -executionpolicy Unrestricted 
                 -command &quot;&amp; invoke-command -scriptblock { 
                          &amp;&apos;$(ScriptLocation)&apos; 
                          &apos;$(LogFileLocation)&apos;  
                          &apos;$(MSDeployComputerName)&apos;}
                          &quot;"/>  
</Target>

ビルド プロセスの一部としてこのターゲットを実行すると、-computername 引数で指定したコンピューターでスクリプトが実行Windows PowerShell。

まとめ

このトピックでは、MSBuild プロジェクト ファイルからWindows PowerShell スクリプトを実行する方法について説明します。 この方法を使用すると、自動またはシングルステップのビルドと展開プロセスの一環として、ローカルまたはリモート コンピューターでWindows PowerShell スクリプトを実行できます。

もっと読む

Windows PowerShellスクリプトの署名と実行ポリシーの管理に関するガイダンスについては、「Windows PowerShell スクリプトの実行」を参照してください。 リモート コンピューターからのWindows PowerShell コマンドの実行に関するガイダンスについては、「リモート コマンドの実行」を参照してください。

カスタム MSBuild プロジェクト ファイルを使用して配置プロセスを制御する方法の詳細については、「 プロジェクト ファイル について」および「 ビルド プロセスについて」を参照してください。