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.

















August 23rd, 2010 at 8:54 pm
Hi, this is very interesting and help me, but now i need to add/remove .cab solution, that is a web part package programmatically too and this way give error, can you help me with this. Thanks for everything anyway.
August 24th, 2010 at 9:29 am
@Liliet: what steps did you try exactly and what errors are you getting?
December 22nd, 2010 at 4:03 am
Thanks for the post. Will the ExecuteJobDefinitions implementation work in a farm scenario? i.e. will it wait until all jobs on all servers are completed? I am asking because we need to deploy more than one solution programatically and want to make sure that each solution is deployed properly to all servers on the farm before deploying the next solution. Does it even matter?
December 22nd, 2010 at 6:44 am
@Gan: In the above code sample I used the reference to the Local Server. In multi-server environment you would need to extend this code to check all servers. There is a tool called WaitForWspJob that might help you: http://blog.michelbarneveld.nl/michel/archive/2010/04/05/waitforwspjob-tool.aspx.
January 17th, 2011 at 2:37 pm
I tried your code but i am facing one error.
System.Security.SecurityException: Access denied. at Microsoft.SharePoint.Administration.SPPersistedObject.BaseUpdate()
I am farm administrator on the machine. Also tried RunWithElevatedPrivileges()
help appreciated.
January 18th, 2011 at 5:03 pm
@Ravi: Running with elevated privileges would decrease your permissions so it's definitely not something that would help you. Which line of code throws the exception you mentioned?
January 18th, 2011 at 5:46 pm
Thanks for the reply Waldek.
I am getting error on solution.Deploy().
I figure out one thing and that is when I deploy my code on central admin site it works fine but its not working on web application other then Central Admin.
I have created web part which deploys solution.
January 24th, 2011 at 6:08 pm
@Ravi: Do you have the stack trace of your exception? That might make it easier to find out what's going on.