После прочтения кучи книг, статей и просмотра видео, обойдя все подводные камни, и сделав наконец свое решение на SharePoint у вас появляется вопрос: “а как его запустить у заказчика?” Visual Studio предательски сама активирует фичи решения по F5 и деактивирует при завершении отладки. А как тоже сделать у заказчика? А если у вас доступа на машину заказчика нет?

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

  1. Добавление WSP-решений уровня фермы
  2. Добавление sandboxed решений
  3. Активация фич
  4. Выполнение дополнительных действий

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

Вроде все просто. Вооружившись справочником по командам PowerShell  для SharePoint попробуем написать скрипт

Add-SPSolution -LiteralPath "SomePath\MySolution.wsp"
Install-SPSolution -Identity "mysolution.wsp" -GACDeployment
Enable-SPFeature MyFeature -Url http://localhost/

Сразу куча проблем:

  1. Работает только из SharePoint Management Shell
  2. Add-SPSolution  не понимает относительных путей
  3. На localhost не будет нужного сайта или надо будет разворачивать в другое место
  4. Sandboxed решения так добавить не получится

Чтобы не заставлять пользователя запускать Management Shell можно написать в начале

Add-PSSnapin Microsoft.SharePoint.Powershell

Но после этого появляется ошибка при запуске из Management shell…

Чтобы обойти проблему нужно проверять загружено ли расширение

if(!(Get-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction:SilentlyContinue))
{
    Add-PSSnapin Microsoft.SharePoint.Powershell
}

Вместо hardcoded параметра сайта можно запрашивать параметр в скрипте с помощью оператора param.  А вот чтобы получить текущий путь скрипта надо использовать хак.

Второй вариант скрипта:

param($siteUrl= $(Read-Host "siteUrl"))

$dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$name = "mysolution.wsp"
$path = "$dir\$name"

if(!(Get-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction:SilentlyContinue))
{
    Add-PSSnapin Microsoft.SharePoint.Powershell
}

Add-SPSolution -LiteralPath $path
Install-SPSolution $name -GACDeployment
Enable-SPFeature MyFeature -Url $siteUrl

Так уже лучше, но тут есть подводный камень. Install-SPSolution в многосерверной конфигурации не сразу развертывает решение, фичи становится доступны когда развертывание завершится на всех серверах. Поэтому надо писать так:

$solution = Install-SPSolution $name -GACDeployment
while($solution.Deployed –eq $false)
{
    sleep -s 1
}

Кроме того очень важно делать установочные (и удаляющие) скрипты идемпотентными, чтобы запуск скрипта много раз давал такой же эффект как запуск скрипта один раз. Для этого можно применить тот же подход, что и при загрузке командлетов SharePoint.

param($siteUrl= $(Read-Host "siteUrl"))

$dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$name = "MySolution.wsp"
$path = "$dir\$name"
$featureId = "6F9619FF-8B86-D011-B42D-00CF4FC964FF" #GUID from Wikipedia

if(!(Get-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction:SilentlyContinue))
{
    Add-PSSnapin Microsoft.SharePoint.Powershell
}

$solution = Get-SPSolution $name -ErrorAction:SilentlyContinue

if(!$solution)
{    
    $solution = Add-SPSolution -LiteralPath $path
}

if($solution.Deployed –eq $false)
{
    Install-SPSolution $solution -GACDeployment
    while($solution.Deployed –eq $false)
    {
        sleep -s 1
    }
}

if(!(Get-SPFeature $featureId -Web $siteUrl -ErrorAction:SilentlyContinue)) #or -Site, -WebApplication, -Farm
{
    Enable-SPFeature $featureId -Url $siteUrl
}

И подобный код повторить для каждого решения и фичи.

Для sandboxed решений будут использоваться другие командлеты Add-SPUserSolution, Install-SPUserSolution и Get-SPUserSolution. Им необходимо дополнительным параметром передать url коллекции сайтов.

Полученный таким образом скрипт можно запускать как из SharePoint Management Shell, так и из explorer. Главное чтобы необходимые wsp файлы лежали рядом с самим скриптом.

UPD. На dev wiki появилась статья на эту тему

Теги : PowerShell, SharePoint