Проблема переноса SPD Workflow с SharePoint Online в SharePoint 2013 On-Premises

Не так давно столкнулся с проблемой, о решении которой хочется поделиться. Реализовывал рабочий процесс непосредственно в SharePoint Online через SharePoint Designer и столкнулся с трудностями переноса на SharePoint 2013 On-Premises. 
При попытке активации решения, мы получали вот такое сообщение:
Sorry, something went wrong
Unable to load assembly group. The user assembly group provider was unable to provide any user assemblies for the specified assembly group.

(К сожалению, что-то пошло не так 

Не удалось загрузить группу сборки. Поставщику группы пользовательской сборки не удалось предоставить пользовательские сборки для указанной группы сборки.)

При детальном изучении логов SharePoint, удалось выяснить что наше решение ссылается на библиотеки SharePoint версии 16, в то время как в SharePoint On-Premises используются библиотеки версии 15. Решить проблему можно и довольно просто, однако нужны ручные операции:

 

  1. Мы знаем, что wsp – это cab-упакованный файл. Соответственно, открываем его через архиватор (WinRAR, 7-zip) и извлекаем всё содержимое
  2. После извлечения ищем файл Feature.xml и открываем его через блокнот
  3. Находим следующую строку: ReceiverAssembly="Microsoft.SharePoint.WorkflowServices, Version=16.0.0.0
  4. Меняем версию с 16 на 15 (ReceiverAssembly="Microsoft.SharePoint.WorkflowServices, Version=15.0.0.0)
  5. Теперь нужно обратно собрать всё в wsp-файл. Есть некоторые архиваторы, которые способны собрать cab-файл и далее его можно переименовать в wsp. Однако, есть еще один красивый способ – С помощью PowerShell и Сборки утилит SharePoint (Microsoft.SharePoint.Utilities.Cab.CabinetInfo)
$destWSPfilename = "<Path where you want to save wsp file>\<filename.wsp>"
$sourceSolutionDir = [System.IO.DirectoryInfo]"<Source from where you are retrieving file>"
$a = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$ctor = $a.GetType("Microsoft.SharePoint.Utilities.Cab.CabinetInfo").GetConstructors("Instance, NonPublic")[0]
$cabInf = $ctor.Invoke($destWSPfilename );
$mi = $cabInf.GetType().GetMethods("NonPublic, Instance, DeclaredOnly")
$mi2 = $null
foreach( $m in $mi ) {
    if( $m.Name -eq "CompressDirectory" -and $m.GetParameters().Length -eq 4 ) {
        $mi2 = $m;
        break;
    };
}
$mi2.Invoke($cabInf, @( $sourceSolutionDir.FullName, $true, -1,$null ));   
   


Где:
<Path where you want to save wsp file> - путь, куда Вы хотите разместить созданный wsp-файл
<filename.wsp> - имя wsp-файла
<Source from where you are retrieving file> - путь до папки, которую необходимо преобразовать в wsp.

Теперь у нового wsp-файла соответствующая версия и проблем, связанных с этим, не будет.


Опубликовано: 18.02.2015
Автор: Владислав Иванов