SharePoint Solution Deployment elements

on Saturday, October 3, 2009

Sharepoint features, webparts, and files are deployed using a solutions file with the extension wsp. The wsp files are actually just a “.cab” file, which is the native Windows archive format. The content of the solutions file must follow a particular schema. Unfortunately, the schema and relationships are not very well documented. The following is an attempt to clear up the confusion.
The Hive
Let’s start backwards from the deployment and look at the hive. The hive is where SharePoint files are installed. When we deploy a solution package using the stsadm.exe command:
stsadm -o addsolution -filename MyFeature.wsp
The stsadm command copies the files from the WSP to the hive. By default, the hive is located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12 on the WSS server.

Typically, when you create a new WSS project, you want to replicate the directory structure of the hive in your project. The reason will become apparent later when we create the solution. In addition, if you plan to use a tool like wspbuilder, the tool expects you to organize the directory in the same manner as the hive.
The Solutions File
Next, we look at the solution, which has an extension of “.wsp”. The solutions file contains everything needed to deploy your software. The solutions file is just a cab file, so we can open it by changing the extension from “.wsp” to “.cab” and then double-click on it.
Here’s an example of the content of a WSP file:

Notice the Manifest.xml file at the beginning. A solution file may hold a variety of different files, but it always has a manifest.xml file. This manifest file list what is in the solutions file. Let’s examine the manifest.xml next.
Manifest.xml file and how it relates to the WSP file
The manifest.xml file specifies how the WSP file is put together. Here’s what the manifest.xml file for the above solutions file looks like:
<Solution SolutionId="4AFC9950-F354-4439-B941-51377E854F2B" xmlns="">

    <FeatureManifest Location="MyFeature\Feature.xml"/>
    <TemplateFile Location="ControlTemplates\MyFeatureForm.ascx"/>

    <Assembly  DeploymentTarget="GlobalAssemblyCache" Location="MyFeature.dll"/>

This manifest tells us that this WSP has an Assembly (the dll), a user control (ascx), and a feature.xml file. There may be additonal files in the WSP. You can even embed a movie into the WSP. But unless the file is specified in the manifest, the installer will skip over it during installation.
The root element of the manifest is always <Solution>. The solution ID is a GUID that uniquely identifies your solution (the deployment package) to SharePoint. When you create a new package, you must always create a new GUID. The other elements specify what is in the WSP file and where to find them via the location attribute. The location is the most confusing part. When I first programmed SharePoint, I thought the location must either closely follow the 12 hive’s file structure or the location must be totally independent of the 12 hive. It turns out that both assumptions are false. The location does actually follow the 12 hives, but the root location will change according to the element type.
Let’s examine the element <FeatureManifest>, the location is based on root of the FEATURES at 12\TEMPLATE\FEATURES. If we deploy this WSP, the location tells it to look for the feature.xml file in MyFeature directory in the WSP file and deploy it to 12\TEMPLATE\FEATURES\MyFeature\feature.xml.
If we take a look at the element <TemplateFile> for the control “MyFeatureForm.ascx”, the location is based on the root of the TEMPLATE, which is at 12\TEMPLATE. If you examine 12\TEMPLATE in the hive, you’ll notice that there is already a CONTROLTEMPLATES and there is already a list of controls there. When we deploy, the manifest will tell the installer that the file MyFeatureForm.ascx is located in ControlTemplates directory in the WSP and that the MyFeatureForm.ascx should be deployed to 12\TEMPLATE\CONTROLTEMPLATES\MyFeatureForm.ascx.

Finally, the <Assembly> element specifies where the DLL is located. The root for this element is the web application bin file if you specify DeploymentTarget=”WebApplication”, and the GAC if you specify DeploymentTarget=”GlobalAssemblyCache”. Hopefully by now, you can guess how this works. In the above example, the <Assembly> element tells the installer to look in the root of the WSP file for the MyFeature.dll and deploy it to the GAC, which is typically located in C:\Windows\System32\Assembly on most systems.
The following is a small table listing the element and where the root of the location in the hive.
Manifest Element
Location’s Root
Web Application bin or GAC
If you understand the concept that each manifest element has a different root, you will be able to use this knowledge to deploy your web asset to any where you want within the hive. For example, suppose you want to group your user controls (ascx) under a folder. So instead of deploying your user control files to 12\TEMPLATE\CONTROLTEMPLATES, you want it to deploy to 12\TEMPLATE\CONTROLTEMPLATES\MyProject. You can change the location from
<TemplateFile Location="ControlTemplates\MyFeatureForm.ascx"/>
<TemplateFile Location="ControlTemplates\MyProject\MyFeatureForm.ascx"/>
Keep in mind that not all combination makes sense or is valid. Features are always limited to one layer deep. If you try to specify location=”MyProject\MyFeature\feature.xml” for a FeatureManifest element, you will get an error message that you cannot go beyond one level deep. In additon, specifying location=”Myproject\MyFeature.dll” doesn’t make sense either because you’ll end up with a subdirectory inside the GAC.

Generating the WSP using a DDF file
While the manifest determines what’s in the WSP file, you still have to create the WSP file itself. Technically, you can manually build the WSP file by hand, but you can use a diamond definition file to build it for you during a compile. A DDF is basically an instruction file for building WSP files. Let’s examine the DDF file used to build the WSP example. This DDF file is placed in the root of the project folder.
; ** sample_wsp.wsp **
.OPTION EXPLICIT     ; Generate errors
.Set CabinetNameTemplate=sample_wsp.wsp
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles="ON"
.Set Cabinet=on
.Set DiskDirectory1=Package
.Set MaxDiskSize=CDROM
Package\sample.dll Package\sample.dll
Config\PowerShell\Registration\cmdlets.xml Config\PowerShell\Registration\cmdlets.xml
The first important line is “CabinetNameTemplate”, which specifies what the outfile file name is going to be. The entry “DiskDirectoryTemplate” may look a bit odd, but it tells the builder where to put the output file. In this case, we say “..\Deployment”. The path is relative to the project’s home directory, so this will generate a Deployment directory into the your Visual Studio’s solution file’s directory and put the WSP file there. The idea is when you compile, all of the WSP file for all projects in the solution will end up in the same deployment directory.

The rest of the DDF handles the adding of files to the WSP archive. You specify the file using a path relative to your project’s root. In the above example, the first file written is manifest.xml and it expects the file to be in the root of the project.
For the assembly, you recall the location for the Assembly in the manifest was location=”MyFeature.dll”. The manifest expects this file to be in the root of the WSP. In your Visual Studio, the path is bin\Release\MyFeature.dll, so the builder will grab the file from your bin directory and add it to the WSP’s root.
The next command is new to us, it said “.SET DestinationDir”. This is because the next item written is feature and the manifest expects it at “MyFeature\Feature.xml”. What we are doing is setting the write directory to “MyFeature” by setting the DestinationDir. Now all files will be written to the MyFeature directory, including the “12\TEMPLATE\FEATURES\MyFeature\feature.xml”.

Finally, we write the user control file. The TemplateFile location in our manifest specifies that it will be located at “ControlTemplates\MyFeatureForm.ascx”. We will use DestinationDir to set it to “ControlTemplates” and then write the user control, which is located in our project at “12\TEMPLATE\ControlTemplates\MyFeatureForm.ascx”.
The DDF file only define how the WSP is build. A utility call makecab does the actualy work. It reads the DDF file, copies the files in the DDF into the wsp. One way to have the files generated automatically is to add a script to the post compile event of your project.
cd "$(ProjectDir)"
MakeCab /f Package.ddf
Now when you compile your project, the event script will run and generate the WSP file.

With tools like WSPBuilder, you can now generate WSP file without fooling around DDF and Manifest files. However, it is still good to understand how the underlying mechanism works. I hope that you have found this article helpful.