После прочтения кучи книг, статей и просмотра видео, обойдя все подводные камни, и сделав наконец свое решение на SharePoint у вас появляется вопрос: “а как его запустить у заказчика?” Visual Studio предательски сама активирует фичи решения по F5 и деактивирует при завершении отладки. А как тоже сделать у заказчика? А если у вас доступа на машину заказчика нет?
Для начала стоит подробнее рассмотреть что же требуется для развертывания вашего решения. Обычно развертывание состоит из нескольких шагов:
- Добавление WSP-решений уровня фермы
- Добавление sandboxed решений
- Активация фич
- Выполнение дополнительных действий
В идеале дополнительные действия должны совершаться при активации фич, поэтому вычеркнем их из данного сценария.
Вроде все просто. Вооружившись справочником по командам PowerShell для SharePoint попробуем написать скрипт
Add-SPSolution -LiteralPath "SomePath\MySolution.wsp" Install-SPSolution -Identity "mysolution.wsp" -GACDeployment Enable-SPFeature MyFeature -Url http://localhost/
Сразу куча проблем:
- Работает только из SharePoint Management Shell
- Add-SPSolution не понимает относительных путей
- На localhost не будет нужного сайта или надо будет разворачивать в другое место
- 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 появилась статья на эту тему