Home
Releases
Discussions
Issue Tracker
Source Code
Stats
People
License
RSS RSS Feed
Search Wiki:
Project Description
A SharePoint Solution Package (WSP) creation tool for WSS 3.0 & MOSS 2007

No more manually creating the manifest.xml file.
No more manually specifying the DDF file.
No more using the makecab.exe application.

The WSPbuilder is a console application that creates SharePoint Solutions files
based on a folder structure. WSPBuilder will automatically traverse a "12" folder structure
and creates a SharePoint solution manifest.xml and the wsp file based on the files it finds.
Therefore you do not need the knowledge of how to create a solution manifest.xml
and wsp file any more.

The folder structure that WSPBuilder uses to build the wsp file is actually the same folder
stucture you will find in: "%Program Files%\Common Files\Microsoft Shared\web server extensions\12"
So all that you have to do, is the create a \12 folder in your project and add your files to
that folder matching the same structure as if you where to put them directly into the
"%Program Files%\Common Files\Microsoft Shared\web server extensions\12" folder manually.

Lets say that you have created a SharePoint feature and you want to create a SharePoint Solution
for this feature. Then you just need to create the following folder structure in you project
directory: "[MyProject]\12\Template\Features\MyCustomFeature\" and put your feature files in
the MyCustomFeature folder, that being your feature. Then run the WSPBuilder from the your project
directory and it will automatically create the manifest.xml and pack it into a wsp file with the
content of the "\12" folder.

The WSPBuilder program fully supports the SharePoint Solution Schema meaning that it is possible
to create any kind of manifest.xml just by using folders. If the Solution Schema supports it, then
WSPBuilder can build it.

Please try out the Demo project and you will see how easy it is.

Before build:
http://www.keutmann.dk/sharepointblog/wspbuilder/wspdemo.jpg

Build:
http://www.keutmann.dk/sharepointblog/wspbuilder/wspbuilderconsole.jpg

After build:
http://www.keutmann.dk/sharepointblog/wspbuilder/buildresult.jpg


See also my blog on the project here http://keutmann.blogspot.com
Last edited Oct 21 2007 at 8:34 PM  by keutmann, version 8
Comments
Also available: 4 reviews for current release.

totmakov wrote  Jul 11 2007 at 12:35 PM  
Super!

I've done task for MSBuild. This task packs items from some directory to wsp. But I was too lazy to add functionality to that task for generating manifest.xml.

I suggest to use wspbuilder and add task to AfterBuild script to call wspbuilder and then to update solution in solution storage. So, you can click "Build" in VS and see how your solution is being packed and updated.

Thanks. :)

P.S. It seems that wspbuilder is worthy of it to be a MSBuild Task... What do you think about it? I can help, if needed.
P.P.S. Maybe New Project Types? Project Item Types?

MarkWagner wrote  Sep 11 2007 at 8:47 PM  
Thank you Carsten Keutmann! This is a MAJOR time saver. I was able to package some third-party controls (Telerik) into a SharePoint solution in literally less than 10 minutes - and it contained a ton of files.

Well Done!

MarkWagner wrote  Sep 11 2007 at 9:34 PM  
continued... There are 1286 files and 142 folders. That would have taken a little more that 10 minutes. :) Thanks again.

marcreynolds wrote  Oct 18 2007 at 1:01 PM  
What a great product and a huge time-saver! I always forget to add/remove file references from the manifest.xml and ddf files, so WSPBuilder prevents a ton of needless errors for me.

While building a web part solution with WSPBuilder, I noticed that the CAS permissions which were being generated were not taking attributes in assembly.cs into account (correct me if I'm wrong). I've added the following line to PolicyItemDefinition.cs just below line 98:

private StringDictionary GetAssemblyDefinedPermissions(Assembly assembly)
{
StringDictionary assemblyPermissions = new StringDictionary();

/* Load Assembly Permissions - Marc Reynolds 2007/10/11 */
AddAttributesToPermissionList(assemblyPermissions, assembly.GetCustomAttributes(typeof(SecurityAttribute), true));

/* Load Class permissions */
foreach (Type type in assembly.GetTypes())
{ ...

keutmann wrote  Oct 21 2007 at 8:13 PM  
Thanks marcreynolds!
The code has now been added to the Source Code. (will be in the next release)

safeldm wrote  Oct 24 2007 at 5:23 PM  
Great release! Has helped me a ton building solution files very quickly.
One issue though buildsafecontrols adds a safecontrol entry for every type of assembly being deployed. I wrote some code to only reflect out types that derive from webpart or control hope this helps.

/// <summary>
/// Adds safe type entries given an assembly reference
/// </summary>
public static void AddSafeTypes(string assemblyRef)
{
Assembly assembly = Assembly.Load(assemblyRef);
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
if (!t.IsAbstract && (t.IsSubclassOf(typeof(WebPart)) || t.IsSubclassOf(typeof(System.Web.UI.WebControls.WebControl)) || t.IsSubclassOf(typeof(System.Web.UI.Control))))
{
AddSafeControlLogicGoesHere
}
}
}

mdikov wrote  Nov 9 2007 at 5:29 PM  
Carsten,
Currently the include/exclude files work only with absolute paths. With the suggested below code WSPBuilder can support both relative and absolute paths in these files:

private StringDictionary LoadWSPFileList(string filename)
{
StringDictionary filelist = new StringDictionary();
if (!String.IsNullOrEmpty(filename))
{
// Load the string lines into the Dictionary
using (StreamReader sr = new StreamReader(filename))
{
while (sr.Peek() >= 0)
{
string filepath = sr.ReadLine();
// Check if the path is absolute
if(!Path.IsPathRooted(filepath))
{
filepath = Path.GetFullPath(filepath);
}

filelist.Add(filepath, string.Empty);
}
sr.Close();
}
}
return filelist;
}

Mikhail Dikov

keutmann wrote  Dec 4 2007 at 6:01 PM  
Thanks Mikhail Dikov, it will be in the next release of WSPBuilder.

keutmann wrote  Dec 4 2007 at 7:22 PM  
Thanks safeldm.
SafeControls method have been updated, it will be in the next release of WSPBuilder.

josephflu wrote  Dec 7 2007 at 6:06 AM  
Nice work! you are saving my neck here with this great utility.

GoodCall wrote  Feb 8 at 1:40 PM  
Super Tool.. and thank you for your help whenever it's needed.

susantha wrote  Mar 6 at 4:10 AM  
It seems very helpful and eazy tool to handle, but I dont have better idea how to use it. How to put my standard .aspx pages and C# code behind pages in WSPBuilder solution. Could you please, refer some materials to use and learn how to use this tool properly deploy into sharepoint?

safeldm wrote  Mar 13 at 4:17 PM  
I put WSPBuilder into the smart search web part and resent it back to the author. Figured the more uses the better. Also provides a great sample on how to use it with custom code and feature deployments. Its now deployed in the latest version.
http://www.codeplex.com/smartsearch.

fgrimm wrote  Mar 26 at 6:34 AM  
Cool Tool!
I've installed the version 1.0.1. i have no context menu. snif.
I think their is a bug in the VS. I have installed a german windows and an english vs.
the addin file is installed under C:\Dokumente und Einstellungen\All Users\Anwendungsdaten\Microsoft\MSEnvShared\Addins. This seems to be correct, but..
the visual studio wants it's addin under C:\Dokumente und Einstellungen\All Users\Application Data\Microsoft\MSEnvShared\Addins. strange!
but it work

mranlett wrote  Apr 2 at 3:09 PM  
Carston - you're my hero man! I'm about to make this tool standard equipment for my company's SharePoint consultants.
I gave you some nice props on my blog: http://blogs.sharepointguys.com/matt/sharepoint-2007-development/when-deploying-code-please-use-solution-packages-for-both-our-sakes/

ChrisMcLean wrote  May 22 at 2:38 PM  
This is a great way to do sharepoint dev! Thanks a ton keutmann!

venkyweb wrote  May 22 at 3:18 PM  
How can I include sample.webpart or sample.dwp entries in generated manifest.xml as below mentioned and add respective files to wsp solution? I do not have any feature to deploy in this case. All I wanted to use this tool to deploy assembly.dll to GAC (which works) and add webparts to site collection during deployment.

<Solution SolutionId="4AFC1350-F354-4439-B941-f5a7039107b5" xmlns="http://schemas.microsoft.com/sharepoint/">


<Assemblies>
<Assembly DeploymentTarget="GlobalAssemblyCache"
Location="ANMDataView.dll">

<SafeControls>
<SafeControl
Namespace="ANMDataView"
TypeName="*" Safe="True"/>
</SafeControls>

</Assembly>
</Assemblies>
<DwpFiles>
<DwpFile FileName="Sample.webpart"/>
<DwpFile FileName="Sample.dwp"/>
</DwpFiles>
</Solution>

jianyi wrote  Jun 9 at 8:39 AM  
WSPBuilder is a wonderfull tool , it's can do almost everything for wsp package. But I want to know if WSPBuilder support to package the resource files in 80\App_GlobalResources folder ?

Indyy66 wrote  Jun 26 at 12:59 PM  
Can you use this tool with Team Fondation Build?

cjvandyk wrote  Aug 23 at 11:35 AM  
Awesome time saving tool! Thanks for sharing it with us.
One thing I ran into on the latest build...
If I configure a WSPBuilder.exe.config with a relative path for the [Outputpath] argument, it does not work.
When I run it from the command line using the same relative path as in ".\Deploy" with the -Outputpath argument i.e.
WSPBuilder.exe -Outputpath .\Deploy
Then it works just fine. Could just be an interpretation issue with the .config file. ;-)
Thanks again for a great product!

Later
C

TheCamel wrote  Aug 28 at 12:27 PM  
Really a good job.
I have made an improvment (see under) to put this all toghether so you can build the solution/register assemblies/copy to hive/recycle app pool/ run ie with url/ attach to w3p, all in one step to improve debugging.

change CommandBase to enable singleton (advantage = you can use them in other commands)
remove contructors
set exec and status as public

change the creation of commands in connect
AllInOne.Instance.Create(this.DTEInstance, false, ProjectBars);
BuildWSP.Instance.Create(this.DTEInstance, true, ProjectBars);
DeployWSP.Instance.Create(this.DTEInstance, false, ProjectBars);
....

Create the new one (change the other commands in the same way)
#region namespace references
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;

using Microsoft.VisualStudio.CommandBars;
using EnvDTE;
using EnvDTE80;
using System.IO;
using Microsoft.Win32;

#endregion

namespace WSPTools.VisualStudio.VSAddIn.Library.Commands
{
public class AllInOne : CommandBase
{
#region ---------------SINGLETON---------------

public static readonly AllInOne Instance = new AllInOne();

/// <summary>
/// Constructeur privé pour forcer le passage par Instance
/// </summary>
private AllInOne()
{
}
#endregion


#region public methods


public void Create(DTEHandler dteHandler, bool beginGroup, CommandBar[] commandbars)
{
Instance.DTEInstance = dteHandler;

Instance.CommandInstance = dteHandler.Menu.CreateCommand(
"ALLINONE",
"&Debug",
"Build/Deploy/Gac/RecycleAppPool/Excute IE/Attach",
"Global::Ctrl+Shift+Alt+B,b",
new ExecuteDelegate(Instance.Execute),
new StatusDelegate(Instance.Status));

dteHandler.Menu.AddToCommandBars(Instance.CommandInstance, beginGroup, commandbars);
}

public override void Execute()
{
if (!BuildSolution()) return;

RegisterAssemblies();

//copy all to the moss directory
CopyTo12Hive.Instance.Execute();

// recycle AppPools
RecycleAppPools.Instance.Execute();

// run ie with the right adress
ExternalProgram externalProgram = new ExternalProgram(this.DTEInstance);
externalProgram.RunAsync(System.Configuration.ConfigurationManager.AppSettings["WebClient"],
System.Configuration.ConfigurationManager.AppSettings["WSPUrl"]);
this.DTEInstance.StatusBar("Done!");

//attach to iis and debug
AttachToWorkerProcesses.Instance.Execute();
}

private void RegisterAssemblies()
{
//register the dll in the gac
WSPFileHandle wspHandle = new WSPFileHandle(this.DTEInstance);
WSPBuilderHandle wspTool = new WSPBuilderHandle(this.DTEInstance);

ExternalProgram externalProgram = new ExternalProgram(this.DTEInstance);
externalProgram.RunAsync(wspTool.WSPToolsPath + "\\gacutil.exe", "/f /il" + wspHandle.SelectedProject.FullPath + "GAC\\ListDLLs.txt");

this.DTEInstance.StatusBar("Done gacutil!");
}

private bool BuildSolution()
{
//Build the solution
this.DTEInstance.Application.Solution.SolutionBuild.Build(true);
if (this.DTEInstance.Application.Solution.SolutionBuild.LastBuildInfo > 0)
{
this.DTEInstance.StatusBar("Build Failed");
return false;
}
else return true;
}

#endregion

}
}

add a config file for the addin
<add key="WSPUrl" value="http://vm/login.aspx" />
<add key="WebClient" value="C:\Program Files\Internet Explorer\iexplore.exe" />
add the gacutil in the wsp folder

Use it, if you like. I will inform you about improvments from my side

torman119 wrote  Sep 29 at 6:13 PM  
Great tool.
Currently we have the following problem:
- Our customer has a large farm with several webapps. He wants to define to which webapp the solution will be deployed.
- We have several WSP solutions without any code (solution only contains xml for site definitions, features, etc.). So WSP Builder will not create the safecontrol entry in the manifest.xml of the wsp solution. But for these WSPs MOSS does not allow to specify a webapp during deployment. These WSPs always deploy globally (to all webapps).
We think, that MOSS only allows the deployment to a specific webapp, when there is a safecontrol enty in the manifest.xml. In this case you can find "Contains Web Application Resource" with "Yes" in the "Solution Properties" page in the CA. In all other case it is set to "No". But we have no assembly :-(

Do you know any solution to force MOSS to deploy a WSP to a specific webapp?
Thanks for any idea.

Updating...