SharePoint Programmatically: Managing Solutions


Managing SharePoint 2007 Solutions programmatically isn’t a daily-matter: some of you might even participate on quite a few projects without even coming close to it. As I have worked with it recently a bit I would like to share my findings with you.

I assume you know what the SharePoint solutions (.wsp packages) are and how do they work. What I’d like to focus on is working with the Solutions programmatically (through the SharePoint Object Model): adding new solutions to the Solution Store, deploying Solutions to Web Applications, retracting and removing them.

First of all let’s take a look at accessing the local Solution Store. For simplicity I will use the local farm. You will probably use the same in your code:

SPFarm.Local.Solutions

Solutions contain all available solutions on the chosen farm.

You can add a Solution to the Solution Store by simply passing the local path to the .wsp file:

string solutionPath = @"C:\somesolution.wsp";
SPSolution solution = SPFarm.Local.Solutions.Add(solutionPath);

Adding a solution to the Solution Store will not overwrite the earlier versions. So if you would like to replace your old .wsp file with a new one, you will need to retract (if deployed) and remove the old one. I will show you how to do it later on.

Adding a solution doesn’t really triggers anything: it just makes the solution available – you still can’t use it though. You need to deploy the solution to a Web Application to actually use it. In the following example I first obtain the Content Web Service using the ContentService property. It allows me to obtain the Web Applications used by SharePoint. Then I select some Web Application where I would like to deploy the solution to.

Collection<SPWebApplication> selectedWebApps =
  new Collection<SPWebApplication>();
SPWebService ws = SPWebService.ContentService;
webApps = ws.WebApplications;
selectedWebApps.Add(webApps["My Web App"]);
selectedWebApps.Add(webApps["SharePoint - 80"]);
solution.Deploy(DateTime.Now, true, selectedWebApps, true);

You need to set the second parameter to true only if your solution needs to deploy some assemblies to the GAC. Otherwise it can be set to false: the assemblies will be deployed to the bin directory of the selected Web Applications.

Your solution has just been added to the local Solution Store and deployed to the selected Web Applications. Now I would like to show you how to retract your solution from the Web Applications where it has been deployed to.

First of all you need to get your solution as an instance of the SPSolution object. Personally I use the custom GetSolutionByName method which allows me to obtain the required solution as object by passing the solution’s name.

private SPSolution GetSolutionByName(string solutionName)
{
  SPSolutionCollection sc = SPFarm.Local.Solutions;
  foreach (SPSolution s in sc)
  {
    if (s.Name.ToLower() == solutionName.ToLower())
      return s;
  }

  return null;
}

To retract the solution:

SPSolution solution = GetSolutionByName(solutionName);
if (solution != null)
{
  if (solution.DeployedWebApplications != null)
  {
    solution.RetractLocal(solution.DeployedWebApplications);
  }

  ExecuteJobDefinitions();
  SPFarm.Local.Solutions.Remove(solution.Id);
}

First of all I use the DeployedWebApplications property of SPSolution to check whether the solution has been deployed at all. If so (the collection is not null), I use the same property to pass the collection of Web Applications where I would like to retract the solution from. As retracting a Solution creates a timer job on the farm you might want to speed it up a bit – especially if you retract the solution right before adding the new version of it:

private void ExecuteJobDefinitions()
{
  if (SPFarm.Local.TimerService.JobDefinitions != null)
  {
    foreach (SPJobDefinition job in
      SPFarm.Local.TimerService.JobDefinitions)
    {
      try
      {
        job.Execute(SPServer.Local.Id);
      }
      catch { }
    }

  }
}

The last part is to remove the solution from the Solution store by passing its ID to the Remove method. Retracting and removing a Solution prevent you from getting an error while installing a Solution that already exists.

So, where could you make use of all this? The above might come handy while deploying your solutions on your customers’ machine - especially if you have created a product-like solution and you would like to ship it with a user-friendly setup. Another usage scenario could be using features for deploying solutions and scaling the deployment.

Others found also helpful: