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.
