Запуск скриптов Windows PowerShell из файлов проекта MSBuild

Джейсон Ли

В этом разделе описывается запуск скрипта Windows PowerShell в рамках процесса сборки и развертывания. Скрипт можно запускать локально (другими словами, на сервере сборки) или удаленно, например на целевом веб-сервере или сервере базы данных.

Существует множество причин, по которым может потребоваться запустить скрипт Windows PowerShell после развертывания. Например, вы можете захотеть:

  • Добавьте в реестр пользовательский источник событий.
  • Создайте каталог для загрузки файлов в файловую систему.
  • Очистка каталогов сборки.
  • Запись записей в пользовательский файл журнала.
  • Отправьте сообщения электронной почты, приглашающие пользователей в только что подготовленное веб-приложение.
  • Создайте учетные записи пользователей с соответствующими разрешениями.
  • Настройте репликацию между экземплярами SQL Server.

В этом разделе показано, как запускать сценарии Windows PowerShell как локально, так и удаленно из пользовательского целевого объекта в файле проекта Microsoft Build Engine (MSBuild).

Этот раздел является частью серии учебников, основанных на требованиях к развертыванию предприятия вымышленной компании Fabrikam, Inc. В этой серии учебников используется пример решения — решение Contact Manager— для представления веб-приложения с реалистичным уровнем сложности, включая приложение MVC 3 ASP.NET MVC 3, службу Windows Communication Foundation (WCF) и проект базы данных.

Метод развертывания в центре этих учебников основан на подходе к разделенному файлу проекта, описанному в разделе "Общие сведения о файле проекта", в котором процесс сборки управляется двумя файлами проекта — одним из них содержит инструкции по сборке, которые применяются к каждой целевой среде, а также один из них содержит параметры сборки и развертывания для конкретной среды. Во время сборки файл проекта для конкретной среды объединяется в файл проекта, не зависящем от среды, чтобы сформировать полный набор инструкций по сборке.

Обзор задачи

Чтобы запустить скрипт Windows PowerShell в рамках автоматизированного или одношагового процесса развертывания, вам потребуется выполнить следующие высокоуровневые задачи:

  • Добавьте сценарий Windows PowerShell в ваше решение и в систему контроля версий.
  • Создайте команду, которая вызывает скрипт Windows PowerShell.
  • Экранируйте все зарезервированные XML-символы в команде.
  • Создайте целевой объект в пользовательском файле проекта MSBuild и используйте задачу Exec для выполнения команды.

В этом разделе показано, как выполнять эти процедуры. Задачи и пошаговые руководства в этом разделе предполагают, что вы уже знакомы с целевыми объектами и свойствами MSBuild, и что вы понимаете, как использовать пользовательский файл проекта MSBuild для управления процессом сборки и развертывания. Дополнительные сведения см. в разделе "Общие сведения о файле проекта " и " Общие сведения о процессе сборки".

Создание и добавление скриптов Windows PowerShell

Задачи в этом разделе используют пример скрипта Windows PowerShell с именем LogDeploy.ps1 для иллюстрации запуска скриптов из MSBuild. Скрипт LogDeploy.ps1 содержит простую функцию, которая записывает запись с одной строкой в файл журнала:

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 принимает два параметра. Первый параметр представляет полный путь к файлу журнала, в который требуется добавить запись, а второй параметр представляет место развертывания, которое требуется записать в файле журнала. При запуске скрипта он добавляет строку в файл журнала в следующем формате:

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

Чтобы сделать скрипт LogDeploy.ps1 доступным для MSBuild, необходимо:

  • Добавьте скрипт в систему управления версиями.
  • Добавьте сценарий в решение в Visual Studio 2010.

Вам не нужно развертывать скрипт с содержимым решения независимо от того, планируется ли запускать скрипт на сервере сборки или на удаленном компьютере. Одним из вариантов является добавление скрипта в папку решения. В примере Contact Manager, так как вы хотите использовать скрипт Windows PowerShell как часть процесса развертывания, необходимо добавить сценарий в папку решения для публикации.

В примере менеджера контактов, так как вы хотите использовать скрипт Windows PowerShell в процессе развертывания, необходимо добавить сценарий в папку решения 'Publish'.

Содержимое папок решения копируется для создания серверов в качестве исходного материала. Однако они не являются частью каких-либо выходных данных проекта.

Выполнение скрипта Windows PowerShell на сервере сборки

В некоторых сценариях может потребоваться запустить скрипты Windows PowerShell на компьютере, на котором создаются проекты. Например, можно использовать скрипт Windows PowerShell для очистки папок сборки или записи в пользовательский файл журнала.

С точки зрения синтаксиса выполнение скрипта Windows PowerShell из файла проекта MSBuild совпадает с запуском скрипта Windows PowerShell из обычной командной строки. Необходимо вызвать исполняемый файл powershell.exe и использовать параметр -command, чтобы запустить команды, которые вы хотите, чтобы выполнял Windows PowerShell. (В Windows PowerShell версии 2 можно также использовать параметр -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 выполнять только подписанные скрипты.

Политика выполнения по умолчанию ограничена, что предотвращает запуск файлов скриптов Windows PowerShell.

Наконец, необходимо экранировать все зарезервированные XML-символы, которые встречаются в вашей команде Windows PowerShell.

  • Замените одинарные кавычки на '

  • Замените двойные кавычки на "

  • Замените амперсанды на &

  • При внесении этих изменений команда будет выглядеть следующим образом:

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 . Это позволяет выполнять скрипт на одном или нескольких удаленных компьютерах без копирования скрипта на удаленные компьютеры. Все результаты возвращаются на локальный компьютер, с которого вы выполнили скрипт.

Замечание

Прежде чем использовать командлет 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' } "

Как и раньше, необходимо указать некоторые дополнительные коммутаторы и экранировать все зарезервированные XML-символы при выполнении команды в MSBuild.

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;

Наконец, как и раньше, можно использовать задачу Exec в пользовательском целевом объекте MSBuild для выполнения команды:

<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>

При выполнении этого целевого объекта в процессе сборки Windows PowerShell будет запускать скрипт на компьютере, указанном в аргументе -computername .

Conclusion

В этом разделе описано, как запустить скрипт Windows PowerShell из файла проекта MSBuild. Этот подход можно использовать для запуска скрипта Windows PowerShell локально или на удаленном компьютере в рамках автоматизированного или одношагового процесса сборки и развертывания.

Дальнейшее чтение

Рекомендации по подписанию сценариев Windows PowerShell и управлению политиками выполнения см. в статье "Запуск сценариев Windows PowerShell". Инструкции по выполнению команд Windows PowerShell с удаленного компьютера см. в разделе "Выполнение удаленных команд".

Дополнительные сведения об использовании пользовательских файлов проекта MSBuild для управления процессом развертывания см. в разделе "Общие сведения о файле проекта " и "Общие сведения о процессе сборки".