Solution Deployment with SharePoint 2007
Code download available at: Office Space 2007_08.exe(229 KB)
Deploying the OfficeSpaceFeature Component
Generating the CAB File for a Solution Package
In the May 2007 issue of MSDN® Magazine, I discussed the fundamental concepts involved in developing custom features and application pages to create business solutions with Windows® SharePoint® Services (WSS) 3.0. Features and application pages represent two types of WSS components that are the primary building blocks a developer can use to extend a SharePoint 2007 site. There are several other WSS component types used in SharePoint development, including site definitions, page templates, Web Parts, event handlers, and workflows.
While my May column focused on how to create, test, and debug WSS components, this month I’ll look at the deployment side. Once you have fully tested a set of components, WSS provides an approach to move your development efforts into a staging or production environment. More specifically, WSS 3.0 introduces a new deployment mechanism, known as a solution package, that allows you to create an installation procedure that is supported, testable, and repeatable. What’s really nice about solution packages is that they allow you to create a single distributable file that abstracts away the details of whether the deployment target is a single SharePoint server or an enterprise-scale server farm with multiple front-end Web servers.
Solution packages are the preferred mechanism for deploying WSS components. The solution package itself is a compressed CAB file with a .wsp extension, and it contains one or more WSS components along with any dependent files that need to be deployed on each front-end Web server.
A simple solution package might contain just the files needed to deploy a single feature. A more complex package could contain the files for multiple features, applications pages, Web Parts, list definitions, event handlers, and a site definition. You decide what goes into a solution package according to what set of components it makes sense to deploy as a single unit.
The WSS runtime provides a built-in installer component that runs on each front-end Web server and is responsible for uncompressing the files inside a solution package and properly installing its components. The WSS installer requires each solution package to carry additional metadata inside a file named manifest.xml. When the installer is called upon to deploy a solution package, it reads the metadata in manifest.xml to determine exactly which components and files from inside the CAB file need to be extracted and deployed.
Manifest.xml contains metadata to instruct the installer which files need to be extracted from the solution packages and copied into various WSS system directories. But beyond that, manifest.xml also carries metadata that tells the installer to perform other important deployment procedures, such as registering features with the WSS runtime, adding assembly DLLs to the Global Assembly Cache (GAC), and updating the web.config file with SafeControl entries required in Web Part deployment.
Deploying the OfficeSpaceFeature Component
In the May column, I presented a business solution composed of a feature named OfficeSpaceFeature that works together with a custom application page named LetterGenerator.aspx. These two components were designed to work together to create a single business solution.
The sample code that accompanies this month’s column contains a Visual Studio® project named OfficeSpaceFeature. This project contains the source code for both the feature and the application page. While the sample code that accompanied the May column had an earlier version of this project, the download has now been updated to include the extra files needed to build and deploy all the required components and files as a solution package. Note that the project contains a \Solution directory and a \Package directory as shown in Figure 1.
Figure 1** Solution Package Components **
When the OfficeSpaceFeature is activated within the context of a SharePoint site, it provisions a document library named Customer Letters. It also provisions a custom template file named LetterTemplate.docx, which serves as the document template behind the Customer Letters document library. This means that LetterTemplate.docx becomes a dependent file that must be deployed along with the feature within the \FEATURES directory on each front-end Web server.
The feature named OfficeSpaceFeature has also been created with an event handler that fires during feature activation. This event handler is defined within a SPFeatureReceiver-derived class and is compiled into an assembly named OfficeSpaceFeature.dll. WSS requires that any assembly DLL containing event handlers be compiled with a strong name and installed into the GAC to work properly.
Now that you have a basic idea of what components and files make up this business solution, let’s examine the feature.xml file for the feature named OfficeSpaceFeature (see Figure 2). As many other XML-based files used in WSS development, the feature.xml file contains XML that conforms to a WSS-specific language known as Collaborative Application Markup Language (CAML).
Figure 2 Feature.xml for OfficeSpaceFeature
<Feature Id=”AAEC2E08-1CCF-4712-AE5E-A33BEA53A325” Title=”A Sample Office Space Feature” Description=”Demoware from Ted Pattison’s Office Space column” Version=”188.8.131.52” Scope=”Web” ImageUrl=”OfficeSpace/PithHelmet.gif” ReceiverAssembly=”OfficeSpaceFeature, [full four-part assembly name]” ReceiverClass=”OfficeSpaceFeature.FeatureReceiver” xmlns=”http://schemas.microsoft.com/sharepoint/”> <ElementManifests> <ElementManifest Location=”elements.xml” /> <ElementFile Location=”LetterTemplate.docx” /> </ElementManifests> </Feature>
The Feature element contains an ElementManifests element, which includes both an inner ElementManifest element and an ElementFile element. ElementManifest references a file named elements.xml that contains the CAML to define ListInstance elements, which provision a new document library and a new list. There is also a Module element used to copy LetterTemplate.docx into the context of the current site during Feature activation so it can serve as the document template behind the Customer Letters document library.
The ElementManifest element is an essential part of the Feature definition because it references elements.xml. That file, in turn, adds provisioning instructions that are carried out during Feature activation. But what is the purpose of the ElementFile element? It doesn’t really change the behavior of the Feature itself. Instead, its purpose is to add metadata used by the installer when the Feature has been included within a solution package. The ElementFile element informs the installer that LetterTemplate.docx must be copied to the OfficeSpaceFeature directory as part of the deployment process.
Now let’s turn our attention to the CAML defined in the manifest.xml file (see Figure 3). The manifest.xml file contains a top-level Solution element, which contains inner elements that reference components and files.
Figure 3 Manifest.xml
<Solution SolutionId=”848ACD1F-DEBC-4078-B21D-56CECE3F499B” xmlns=”http://schemas.microsoft.com/sharepoint/”> <FeatureManifests> <FeatureManifest Location=”OfficeSpaceFeature\feature.xml” /> </FeatureManifests> <TemplateFiles> <TemplateFile Location=”LAYOUTS\OfficeSpace\LetterGenerator.aspx” /> <TemplateFile Location=”IMAGES\OfficeSpace\PithHelmet.gif”/> </TemplateFiles> <Assemblies> <Assembly DeploymentTarget=”GlobalAssemblyCache” Location=”OfficeSpaceFeature.dll” /> </Assemblies> </Solution>
Note that the Solution element contains a SolutionId attribute whose value is assigned a unique GUID used to identify the solution package. There is also a FeatureManifest element that references the feature.xml file for the feature named OfficeSpaceFeature. Feature.xml references elements.xml and LetterTemplate.docx so that these two files are implicitly included as part of the solution package.
Next, take a look at the two TemplateFile elements nested inside the TemplateFiles element. The first TemplateFile element references the application page named LetterGenerator and specifically defines its path within the custom \OfficeSpace directory, which is located inside the \LAYOUTS directory. The second TemplateFile element references a graphic image file named PithHelmet.gif that will be deployed inside the \IMAGES directory. You should observe that the path assigned to the Location attribute within a TemplateFile element is relative to the \TEMPLATE directory.
The last element inside manifest.xml we need to examine is the Assembly element used to deploy OfficeSpaceFeature.dll into the GAC. Note that many types of WSS components that are compiled into assembly DLLs must be installed into the GAC as shown in Figure 3. Assembly DLLs containing Web Parts provide the option of installation in either the GAC or the bin directory of the hosting Web Application.
Generating the CAB File for a Solution Package
Now that you have seen what files need to be added to a solution package, let’s look at the steps involved in building the CAB file. Today, this is unfortunately a manual and somewhat tedious process. Given the lack of productivity tools, the most common approach involves using the makecab.exe tool. When you use this tool, you must define a .ddf file that tells makecab.exe what files to include in the output CAB file. Take a look at the file named CAB.ddf (see Figure 4), which is used to generate the solution package named OfficeSpaceFeature.wsp.
Figure 4 CAB.ddf
.OPTION EXPLICIT .Set CabinetNameTemplate=OfficeSpaceFeature.wsp .Set DiskDirectory1=Package .Set Cabinet=on .Set MaxDiskSize=0 .Set CompressionType=MSZIP; .Set DiskDirectoryTemplate=CDROM; Solution\manifest.xml manifest.xml TEMPLATE\FEATURES\OfficeSpaceFeature\feature.xml OfficeSpaceFeature\feature.xml TEMPLATE\FEATURES\OfficeSpaceFeature\elements.xml OfficeSpaceFeature\elements.xml TEMPLATE\FEATURES\OfficeSpaceFeature\LetterTemplate.docx OfficeSpaceFeature\LetterTemplate.docx TEMPLATE\LAYOUTS\OfficeSpace\LetterGenerator.aspx LAYOUTS\OfficeSpace\LetterGenerator.aspx TEMPLATE\IMAGES\OfficeSpace\PithHelmet.gif IMAGES\OfficeSpace\PithHelmet.gif bin\Debug\OfficeSpaceFeature.dll OfficeSpaceFeature.dll
As you can see, CAB.ddf begins with header attributes such as CabinetNameTemplate, which defines the name of the output CAB file. After that there is a separate line for each file that needs to be compiled into OfficeSpaceFeature.wsp. The first element in each line points to the location where the makecab.exe utility can find the file so it can copy it into the CAB file. For example, the path to feature.xml as it exists within the directory structure of the Visual Studio project is defined with this path:
The second entry in each line points to the location the file will have once it has been compressed into the CAB file. For example, the feature.xml file must be added to a directory named OfficeSpaceFeature:
Now that you have seen what CAB.ddf looks like, it’s time to put this file to work and use it to build the solution package using the makecab.exe utility. Note that the project structure shown in Figure 1 shows a separate directory named \Package that includes four batch files. These batch files script the important interaction between the makecab.exe and the stsadm.exe command line utilities. Let’s look at the batch file named CreateSolutionPackage.cmd that automates the call to makecab.exe and builds the solution package named OfficeSpaceFeature.wsp:
@echo off if EXIST OfficeSpaceFeature.wsp del OfficeSpaceFeature.wsp cd .. makecab.exe /f Solution\cab.ddf cd Package
You can see this batch file deletes the previous build of OfficeSpaceFeature.wsp if one already exists. It then changes directories to the main project directory so that when makecab.exe runs, the file references in CAB.ddf are correct. After running this batch file, you should have a newly generated build of the solution package named OfficeSpaceFeature.wsp.
If you are curious and you want to look at what has been compressed inside, you can change the file extension from .wsp to .cab and double-click on the file. Windows will then open the file as it would any other CAB file and display an internal view of its contents, as shown in Figure 5.
Figure 5** Looking Inside OfficeSpaceFeature.wsp **(Click the image for a larger view)
Once you have built a solution package such as OfficeSpaceFeature.wsp, you deploy it within a SharePoint farm in two distinct steps. The first step is installation in which WSS copies the .wsp file to the configuration database. The second step involves the actual deployment in which WSS creates a timer job to be processed by all front-end Web servers in the server farm. The important observation here is that WSS automates solution package deployment across all the front-end Web servers in the farm to ensure a consistent deployment.
Let’s look at the next batch file named InstallSolutionPack age.cmd. It included a single command to the stsadm.exe command-line utility to run an operation named addsolution:
@SET STSADM=”c:\program files\common files\microsoft shared\ web server extensions\12\bin\stsadm.exe” %STSADM% -o addsolution -filename OfficeSpaceFeature.wsp
This is the operation that copies the solution package file into the configuration database and makes it available for deployment. At this point you have the option of deploying the solution package with another batch file or by using the standard user interface provided by the SharePoint 3.0 Central Administration Web site.
Keep in mind that deploying a solution package has a definite impact on a SharePoint farm. The deployment process on each front-end Web server involves copying files into WSS system directories, installing features, and adding assembly DLLs to the GAC. Furthermore, WSS always runs a command to restart all the IIS worker processes that might be effected by the new components that have just been installed. For this reason, in production environments you should deploy solution packages during off hours when the fewest number of users are using the system. Fortunately, WSS provides the convenience to schedule deployment jobs for a future time and date. For example, an administrator can schedule a deployment job for 1 A.M. to reduce or eliminate its impact on users.
My sample solution uses a batch file named DeploySolutionPackage.cmd. This batch file makes several calls to the stsadm.exe command-line utility. The first call runs the addsolution operation and is followed by a second call that runs the deploysolution operation:
@SET STSADM=”c:\program files\common files\microsoft shared\web server extensions\12\bin\stsadm.exe” %STSADM% -o addsolution -filename OfficeSpaceFeature.wsp %STSADM% -o deploysolution -name OfficeSpaceFeature.wsp -immediate - allowGacDeployment %STSADM% -o execadmsvcjobs
In the call to stsadm.exe that runs the deploysolution operation, I have passed the parameters -immediate and -allowGacDeployment. The -immediate parameter instructs WSS to run the job right away. There are other parameters that can be passed to schedule a timer job for this deployment at some time in the future. The -allowGacDeployment parameter is required in this case because the solution package is installing an assembly DLL in the GAC.
Now look at the final call to the stsadm.exe command-line utility to run the execadmsvcjobs operation. This is a handy call to use when you are testing a solution package. This call has the effect of forcing WSS to run any pending timer jobs such as a solution package deployment job. Therefore, you don’t have to sit around and wait for WSS to start the deployment job.
Another powerful aspect of solution package deployment is that it supports retraction. That gives you the ability to effectively remove any WSS components and files that have been installed using a solution package.
Let’s take a look at the batch filed named DeleteSolutionPackage.cmd, which lets you undo a deployment.
@SET STSADM=”c:\program files\common files\microsoft shared\ web server extensions\12\bin\stsadm.exe” %STSADM% -o retractsolution -name OfficeSpaceFeature.wsp -immediate %STSADM% -o execadmsvcjobs %STSADM% -o deletesolution -name OfficeSpaceFeature.wsp
As you can see, the retractsolution operation is used to roll back a solution package deployment. In this case, running this batch file removes the assembly DLL from the GAC, uninstalls the Feature, and removes all files that were initially copied to the file system of the front-end Web server during solution package deployment.
This month’s column stepped through the concepts and basic steps of deployment using solution packages. Packaging up and deploying your WSS development efforts using solution packages is a best practice, and knowing how to do this should be considered an essential skill. It is also recommended that you test your solution package in an environment that is not the same as your development environment such as a clean Virtual PC image or a multi-server SharePoint farm that your company uses for staging and quality assurance testing. Using a disciplined approach like this will allow you to roll out custom WSS components such as features, site definitions, Web Parts, and workflows with confidence.
Send your questions and comments for Ted to firstname.lastname@example.org.
Ted Pattison is an author, trainer, and SharePoint MVP who lives in Tampa, Florida. Ted has just completed his book Inside Windows SharePoint Services 3.0 for Microsoft Press. He also delivers advanced SharePoint training to professional developers through his company, Ted Pattison Group.