Wednesday, July 30, 2014

Upload sandbox solutions to Sharepoint Online via PowerShell

Most of Sharepoint developers often deployed farm solutions to Sharepoint web application using Add-SPSolution and Install-SPSolution PowerShell cmdlets. In order to deploy sandbox solutions to on-premise Sharepoint sites we can use appropriate sandbox versions of mentioned cmdlets: Add-SPUserSolution and Install-SPUserSolution. Unfortunately these cmdlets work only on-premise. But how to upload sandbox solution to Sharepoint Online site?

In order to do it we may use Sharepoint Online helper open source project which is hosted on Codeplex. It makes changes in solutions gallery by using client object model. For authentication you have to provide your user name and password for Sharepoint Online site. They will be used for getting authentication cookies which then will be used for making authenticated requests.

At the moment of writing this post it had the following methods for managing sandbox solutions in Sharepoint Online:

  • Upload solution
  • Activate solution
  • Deactivate solution

Unfortunately for complete set of methods it didn’t contain Delete solution method. So first of all we need to add this method to the library. Code is hosted on codeplex with compiled library, so it is quite easy to do:

   1: public static void DeleteSolution(String siteCollectionUrl,
   2:     CookieContainer cookies, String filePath)
   3: {
   4:     siteCollectionUrl = siteCollectionUrl.TrimEnd('/');
   5:     var fileInfo = new FileInfo(filePath);
   6:     var ctx = Authenticator.GetClientContext(siteCollectionUrl, cookies);
   7:  
   8:     var fileUrl = String.Format("{0}/_catalogs/solutions/{1}",
   9:         siteCollectionUrl, fileInfo.Name);
  10:     var fileUri = new Uri(fileUrl);
  11:  
  12:     Microsoft.SharePoint.Client.File file =
  13:         ctx.Web.GetFileByServerRelativeUrl(fileUri.AbsolutePath);
  14:     ctx.Load(file);
  15:     file.DeleteObject();
  16:     ctx.ExecuteQuery();
  17: }

I also provided patch with this method on project’s site. After that we have all methods we need for managing sandbox solutions on Sharepoint Online site.

Next step is to write PowerShell script for uploading, activating, deactivating and deleting solutions remotely:

   1: param(
   2:     [switch]$uploadSolution,
   3:     [switch]$deactivateSolution,
   4:     [switch]$activateSolution,
   5:     [switch]$deleteSolution,
   6:     [switch]$updateSolution
   7: )
   8:  
   9: . ./Params.ps1
  10:  
  11: [System.Reflection.Assembly]::LoadFile([System.IO.Path]
  12: ::Combine($externalDllsDirectory, "Microsoft.SharePoint.Client.dll"))
  13: [System.Reflection.Assembly]::LoadFile([System.IO.Path]
  14: ::Combine($externalDllsDirectory, "Microsoft.SharePoint.Client.Runtime.dll"))
  15: [System.Reflection.Assembly]::LoadFile([System.IO.Path]
  16: ::Combine($externalDllsDirectory, "SharePointOnline.Helper.dll"))
  17:  
  18: function Get-Auth-Cookies()
  19: {
  20:     Write-Host "Get authentication cookies from O365-foregroundcolor Green
  21:     $cookies = [SharePointOnline.Helper.Authenticator]
  22: ::GetAuthenticatedCookies($siteCollUrl, $login, $password)
  23:     return $cookies
  24: }
  25:  
  26:  
  27: function Upload-Solution-Impl($cookies)
  28: {
  29:     Write-Host "Upload solution $solutionName to $siteCollUrl"
  30: -foregroundcolor Green
  31:     [SharePointOnline.Helper.SandboxSolutions]
  32: ::UploadSolution($siteCollUrl, $cookies, $solutionFullPath)
  33:     Write-Host "Solution was successfully uploaded" -foregroundcolor Green
  34: }
  35:  
  36: function Upload-Solution()
  37: {
  38:     $cookies = Get-Auth-Cookies
  39:     Upload-Solution-Impl $cookies
  40: }
  41:  
  42: function Activate-Solution-Impl($cookies)
  43: {
  44:     Write-Host "Activate solution $solutionName on $siteCollUrl"
  45: -foregroundcolor Green
  46:     [SharePointOnline.Helper.SandboxSolutions]
  47: ::ActivateSolution($siteCollUrl, $cookies, $solutionName)
  48:     Write-Host "Solution was successfully activated" -foregroundcolor Green
  49: }
  50:  
  51: function Activate-Solution()
  52: {
  53:     $cookies = Get-Auth-Cookies
  54:     Activate-Solution-Impl $cookies
  55: }
  56:  
  57: function Deactivate-Solution-Impl($cookies)
  58: {
  59:     Write-Host "Deactivate solution $solutionName on $siteCollUrl"
  60: -foregroundcolor Green
  61:     [SharePointOnline.Helper.SandboxSolutions]
  62: ::DeactivateSolution($siteCollUrl, $cookies, $solutionName)
  63:     Write-Host "Solution was successfully deactivated" -foregroundcolor Green
  64: }
  65:  
  66: function Deactivate-Solution()
  67: {
  68:     $cookies = Get-Auth-Cookies
  69:     Deactivate-Solution-Impl $cookies
  70: }
  71:  
  72: function Delete-Solution-Impl($cookies)
  73: {
  74:     Write-Host "Delete solution $solutionName from $siteCollUrl"
  75: -foregroundcolor Green
  76:     [SharePointOnline.Helper.SandboxSolutions]
  77: ::DeleteSolution($siteCollUrl, $cookies, $solutionName)
  78:     Write-Host "Solution was successfully deleted" -foregroundcolor Green
  79: }
  80:  
  81: function Delete-Solution()
  82: {
  83:     $cookies = Get-Auth-Cookies
  84:     Delete-Solution-Impl $cookies
  85: }
  86:  
  87: function Update-Solution()
  88: {
  89:     $cookies = Get-Auth-Cookies
  90:     Deactivate-Solution-Impl $cookies
  91:     Delete-Solution-Impl $cookies
  92:     Upload-Solution-Impl $cookies
  93:     Activate-Solution-Impl $cookies
  94: }
  95:  
  96: # solutions management
  97: if ($uploadSolution)
  98: {
  99:     Upload-Solution
 100: }
 101:  
 102: if ($activateSolution)
 103: {
 104:     Activate-Solution
 105: }
 106:  
 107: if ($deactivateSolution)
 108: {
 109:     Deactivate-Solution
 110: }
 111:  
 112: if ($deleteSolution)
 113: {
 114:     Delete-Solution
 115: }
 116:  
 117: if ($updateSolution)
 118: {
 119:     Update-Solution
 120: }

In Params.ps1 script we define path to solution on local file system, site url, user name and password for Sharepoint Online:

   1: # Configure environment specific variables here.
   2: # Use absolute paths if needed.
   3: $currentPath = Convert-Path(Get-Location)
   4: $externalDllsDirectory = resolve-path($currentPath + "\ExternalDll\")
   5: $packageDirectory = resolve-path($currentPath + "\Packages\")
   6: $solutionName = "Test.wsp"
   7: $solutionFullPath = [System.IO.Path]::Combine($packageDirectory, $solutionName)
   8:  
   9: $siteCollUrl = "http://example.com"
  10: $login = "login"
  11: $password = "password"

After that in order to update our solution (deactivate, delete, upload and activate) we may use the following command:

   1: .\install.ps1 -updateSolution

Also we may execute mentioned tasks separately if needed. I hope that this article will be useful and will help you in your work.

1 comment:

  1. Hello,
    I have tried your code with powershell as well as code.while running i am getting error "The remote server returned an error: (403) Forbidden.".Please suggest me if i am doing something wrong.

    Thanks

    ReplyDelete