Summary
This fourth post is about creating and using Solutions in a general sense, just as the previous one was about Features. Check the first post SharePoint 2007 Deployment: Overview for an introduction and the series index.
The Solution File
A solution file is a cabinet (.cab
) file with a .wsp
extension which contains a manifest file and, additionally, can contain several other files like:
- Site definitions
- Feature definitions (with their element manifests and element files)
- Web part files (
.dwp
and.webpart
) - Template files
- Root files
- Assemblies
- Code access security policies
The solution file has a hierarchical structure where the manifest file is placed in its root and each feature and other components are placed in dedicated folders.
Note: one very important consideration that must be taken into account when creating a solution is that, the folder structure inside the .wsp
file determines the final folder structure on the SharePoint server when the solution is deployed.
Creating a Solution
Creating a solution is a multiple step process:
- Create the solution manifest file (
Manifest.xml
file) - Create the folder structure with all the components
- Create a Diamond Directive File (
.ddf
file which specifies the.wsp
internal folder structure) - Build the Solution Package (
.wsp
file)
The next sections detail each one of these steps.
Solution Manifest File
The solution manifest file is an XML file that must be named Manifest.xml
and must be placed in the root folder of the .wsp
file. This file references all the components of the solution and defines their locations in the target machine (and consequently in the .wsp
internal folder structure).
This is a sample manifest file for a solution. To make it easier to explain its contents, I will separate the description in sections as indicated by the comments in the file below.
<?xml version="1.0" encoding="utf-8" ?> <Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="{A2E6B7EA-8D64-4a23-80B7-8104A82DF1C1}" DeploymentServerType="ApplicationServer" ResetWebServer="True"> <!-- Resources --> <ApplicationResourceFiles> <ApplicationResourceFile Location="MyFiles\AppResources.pt-PT.resx"/> </ApplicationResourceFiles> <Resources> <Resource Location="MyFirstFeature\MyFeatureResources.pt-PT.resx"/> </Resources> <!-- Web Parts --> <DwpFiles> <DwpFile Location="MyWebPart.webpart"/> </DwpFiles> <!-- Assemblies --> <Assemblies> <Assembly DeploymentTarget="GlobalAssemblyCache" Location="GAC\MyFirstAssembly.dll"> <SafeControls> <SafeControl Assembly="MyFirstAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5968549632b337ff" Namespace="MyNamespace" TypeName="MyClassName" Safe="True"/> </SafeControls> <ClassResources> <ClassResource Location="MyLogo.jpg"/> </ClassResources> </Assembly> <Assembly DeploymentTarget="WebApplication" Location="MySecondAssembly.dll" /> </Assemblies> <!-- Features --> <FeatureManifests> <FeatureManifest Location="MyFirstFeature\Feature.xml"/> <FeatureManifest Location="MySecondFeature\Feature.xml"/> </FeatureManifests> <!-- Root Files --> <RootFiles> <RootFile Location="Resources\MyResources.pt-PT.resx"/> </RootFiles> <!-- Template Files --> <TemplateFiles> <TemplateFile Location="Layouts\MyProduct\CustomPage.aspx"/> <TemplateFile Location="Layouts\MyProduct\MyLogo.jpg"/> </TemplateFiles> <!-- Site Definition Manifests --> <SiteDefinitionManifests> <SiteDefinitionManifest Location="STS"> <WebTempFile Location="1033\STS\webtempSTS.xml"/> </SiteDefinitionManifest> </SiteDefinitionManifests> <!-- Code Access Security --> <CodeAccessSecurity> <PolicyItem> <PermissionSet class="NamedPermissionSet" Description="This code group grants code signed with the Microsoft strong name full trust" Name="Microsoft_Strong_Name" version="1"> <IPermission /> </PermissionSet> <Assemblies> <Assembly Name="System.Security.NamedPermissionSet" PublicKeyBlob="00000000000000000400000000000000" Version="1"/> </Assemblies> </PolicyItem> </CodeAccessSecurity> </Solution>
Solution Element
The root element of the manifest file is the <solution>
element which has four possible attributes:
xmlns
– The namespace. This attribute is mandatory.SolutionId
– Unique ID of the solution. This attribute is mandatory.DeploymentServerType
– Indicates which type of server is the target for the deployment of this solution. Can beApplicationServer
orWebFrontEnd
. This attribute is optional (if not used, the solution is deployed to all the servers in the farm).ResetWebServer
– Indicates if web server should be restarted after the deployment of the solution. Can beTrue
orFalse
. This attribute is optional.
Resources
There are several ways to add resource files to a solution. One of them is through the <ApplicationResourceFiles>
element. This element can have one or more <ApplicationResourceFile>
elements which have a single mandatory attribute Location
. This attribute defines the location of the .resx
file in the internal structure of the solution file.
Resource files added to the solution using this element will be copied to the web application folder inside the IIS folder structure. In the sample above, assuming the solution was deployed to the web application in port 80, it would be placed in:
C:\Inetpub\wwwroot\wss\VirtualDirectories\80\Resources\MyFiles\AppResources.pt-PT.resx
Another way of adding resource files to a solution is through the <Resources>
element. Like the previous element, this one can have one or more <Resource>
elements which have a single mandatory attribute Location
. This attribute defines the location of the .resx
file in the internal structure of the solution file.
The difference between the <ApplicationResourceFiles>
element and the <Resources>
element, is that the last one must be used in the context of a feature specifying the location of the file inside the FEATURES
folder. In the sample above, the file would be placed in:
C:\...\12\TEMPLATE\FEATURES\MyFirstFeature\MyFeatureResources.pt-PT.resx
Notes:
- To add generic resource files (not packed in
.resx
files) associated with an assembly, you must used the<Assembly>
element. - To add resource files to SharePoint, independently of a Feature, and Assembly or an Application, use the
<RootFiles>
element.
Web Parts
Web parts are one of the most common components that developers need to deploy to a SharePoint farm. There are several methods to deploy web parts to SharePoint, one of them is using the <DwpFiles>
element. This element can have one or more <DwpFile>
elements which, in turn, have a single mandatory attribute Location. This attribute determines the location of the .webpart
or .dwp
file that contains the web part specification.
This method copies the web part specification file (.webpart
or .dwp
) to the web part gallery of all the site collections of a web application. One important aspect is that this is not enough to deploy a web part. You'll also need to deploy the assembly and optional resource files to SharePoint to get the web part to work.
Assemblies
Creating a solution package is the only way to deploy an assembly to a SharePoint farm. For that, you use the <Assemblies>
element. This element can have one or more <Assembly>
elements, each one bearing two mandatory attributes:
DeploymentTarget
– Specifies if the assembly should be copied to the GAC (if its value isGlobalAssemblyCache
) or to theBIN
folder of the web application (if its value isWebApplication
).Location
– Specifies the path to the assembly inside the solution package. This value is relevant because, when placed in theBIN
folder of the web application, the assembly will be placed in the same folder structure that exists inside the solution package. This means that, if you want to place the assembly in theBIN
folder (and not in any subfolder), you must put it in the root of the solution package.
Additionally, there are two optional child elements for the <Assembly>
element: SafeControls
and ClassResources
.
The <SafeControls>
element allows you to add one or more lines to the SafeControls
section of the web application's web.config
file. This is an essential step if you are deploying a web part or a web control to SharePoint, because without it SharePoint will not allow it to be used. This element can have one or more <SafeControl>
elements, each one with four mandatory attributes:
Assembly
– The full qualified name of the assembly.Namespace
– The namespace of the type to be marked as a safe control.TypeName
– The name of the class that implements the control to be marked as safe. You can use the asterisk (*) character to specify that all types in the assembly are safe.Safe
– Boolean flag that indicates if the type is to be marked safe or unsafe.
If you look closely, you'll see that each <SafeControl>
element has exactly the same format as the line added to the web application's web.config
file.
The <ClassResources>
element allows you to add unpackaged resource files (such as images or XML files) that are used in a particular assembly but weren't embedded in it. This element can have one or more <ClassResource>
elements, each one with a mandatory attribute Location
. This attribute defines the path to the file used as a resource in the assembly.
In the above sample, two assemblies are added:
- The assembly
MyFirstAssembly.dll
is installed in the Global Assembly Cache, and the classMyClassName
, with the namespaceMyNamespace
, is added to theweb.config
as a Safe Control. Additionally, the fileMyLogo.jpg
is added as a resource of this assembly. - The assembly
MySecondAssembly.dll
is copied to theBIN
folder of the web application.
Features
To deploy features to a SharePoint farm, you only need to use the <FeatureManifests>
element. This element can have one or more <FeatureManifest>
elements, each one with a single mandatory attribute Location
. This attribute specifies the path to the Feature.xml
file (the feature manifest) inside the solution package (and inside the FEATURES
folder in the SharePoint folder structure).
When the solution is deployed, the feature manifest file and all the files referenced in it (element manifests and element files) are copied to the folder specified in the Location
attribute, and the feature is installed in the farm.
In the above sample, two features are installed:
- A folder named
MyFirstFeature
is created inside theFEATURES
folder, and theFeature.xml
(and all other element manifests and element files) are copied to it.
C:\...\12\TEMPLATE\FEATURES\MyFirstFeature\Feature.xml
- The same happens to the feature
MySecondFeature
.
Note: you don't need to add the files referenced inside the feature manifest (element manifests and element files) to the solution manifest. During the deployment of the solution, SharePoint will open the feature manifests of each of the features and add the files that are referenced in them.
Root Files
If you wish to copy a certain file to any of the folders in the SharePoint folder structure, you can use the <RootFiles>
element. This element can have one or more <RootFile>
elements, each one with a single mandatory attribute Location
. As in previous elements, this attribute specifies the path to the file inside the solution package (and in the destination folder structure).
Files added using this method are placed inside the root of the SharePoint folder structure:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12
In the above sample, the resource file MyResources.pt-PT.resx
is copied to the global SharePoint resources folder:
C:\...\12\Resources\MyResources.pt-PT.resx
Template Files
If you wish to copy a certain file to the TEMPLATE
folder (or any of its subfolders) in the SharePoint folder structure, you can use the <TemplateFiles>
element. This element can have one or more <TemplateFile>
elements, each one with a single mandatory attribute Location
. Like in root files, this attribute specifies the path to the file inside the solution package (and its destination path).
Files added using this method are placed inside the folder C:\...\12\TEMPLATE
. It's rather common to use this method to place files in the /_layouts
virtual directory, since it is mapped to the folder C:\...\12\TEMPLATE\LAYOUTS
.
In the above sample two files are copied to:
C:\...\12\TEMPLATE\LAYOUTS\MyProduct\CustomPage.aspx
C:\...\12\TEMPLATE\LAYOUTS\MyProduct\MyLogo.jpg
This makes the available inside any SharePoint web site through the URLs:
/_layouts/MyProduct/CustomPage.aspx
/_layouts/MyProduct/MyLogo.jpg
Site Definition Manifests
The <SiteDefinitionManifests>
element allows you to include site definitions in the solution. This element can have one or more <SiteDefinitionManifest>
elements, each one with a single mandatory attribute Location
and child element <WebTempFile>
.
The Location attribute of the <SiteDefinitionManifest>
element specifies the name of the root folder inside C:\...\12\TEMPLATE\SiteTemplates
where the the Site Definition will be placed.
The <WebTempFile>
element also has a Location
attribute that specifies the path to the web template specification file associated with this site definition.
In the above sample, a site definition is deployed to the folder: C:\...\12\TEMPLATE\SiteTemplates\STS
and its specification is included in the file copied to: C:\...\12\TEMPLATE\1033\STS\webtempSTS.xml
.
Code Access Security
The last optional section in the solution manifest is the <CodeAccessSecurity>
element, which allows you to set a Code Access Security policy for the solution. This element can have one or more <PolicyItem>
elements, and each one of these has two child elements: <PermissionSet>
and <Assemblies>
.
The <PermissionSet>
element defines the permissions for this CAS policy, and contains four attributes:
class
– A mandatory attribute that must have the valueNamedPermissionSet
.version
– A mandatory attribute that defines the version of the permission set.Name
– An optional attribute that specifies the name of the permission set.Description
– An optional attribute that specifies a description for the permission set.
Additionally, the <PermissionSet>
element has one or more <IPermission>
child elements. These elements have several optional attributes and child elements, which will not be discussed in the context of this post.
The <Assemblies>
element is composed of one or more <Assembly>
elements, which specify the assemblies associated with this policy item. The <Assembly>
element has three optional attributes:
Name
– The assembly name.PublicKeyBlob
– The public key of the assembly in binary format.Version
– The version of the assembly.
Solution Package Folder Structure
Like it was referred in the beginning of this post, the internal folder structure of a solution package will be reproduced in the destination machine. For that reason, you should follow some simple rules:
- Place the solution manifest (
Manifest.xml
) in the root folder of the package. - Create a folder for each feature, in the root of the solution package. Don't forget each feature must have a feature manifest (
Feature.xml
) in that folder. The same goes for Site Definitions. - All the assemblies that will be copied to the
BIN
folder of the web application should be placed in the root folder of the solution package, so that no subfolders are created in the destinationBIN
folder. - Assemblies that will be copied to the GAC can be placed anywhere since there are no subfolders in the GAC. However, a good practice is to create a folder named GAC in the root of the solution package and place the assemblies inside.
- When using custom web pages or images, create a
LAYOUTS
folder in the root of the solution package. Inside that folder create a folder structure of your choice ([Company Name]\[Product Name]
for instance) and place the files inside. In the solution manifest use the<TemplateFiles>
element specify the deployment destination.
The Diamond Directive File
To build a solution package (which is essentially a .cab
file) you'll need to define a Diamond Directive File (.ddf
file) which defines its internal folder structure. You can find several tools that help you this, but knowing how to do it manually can always come handy.
The DDF is a text file with a specific syntax that defines the folder into which each file will be placed when the package is generated. See below a sample of a DDF that goes with the above solution manifest.
; HEADER .OPTION EXPLICIT .Set CabinetNameTemplate=MySolution.wsp .Set DiskDirectoryTemplate=CDROM .Set CompressionType=MSZIP .Set UniqueFiles=Off .Set Cabinet=On .Set DiskDirectory1=Package ; ROOT FOLDER manifest.xml MyWebPart.webpart MyLogo.jpg MySecondAssembly.dll ; GAC FOLDER .Set DestinationDir=GAC GAC\MyFirstAssembly.dll ; MyFiles FOLDER .Set DestinationDir=MyFiles MyFiles\AppResources.pt-PT.resx ; MyFirstFeature FOLDER .Set DestinationDir=MyFirstFeature MyFirstFeature\Feature.xml MyFirstFeature\MyFeatureResources.pt-PT.resx ; MySecondFeature FOLDER .Set DestinationDir=MySecondFeature MySecondFeature\Feature.xml ; Resources FOLDER .Set DestinationDir=Resources Resources\MyResources.pt-PT.resx ; Layouts\MyProduct FOLDER .Set DestinationDir=Layouts\MyProduct Layouts\MyProduct\CustomPage.aspx Layouts\MyProduct\MyLogo.jpg ; 1033\STS FOLDER .Set DestinationDir=1033\STS 1033\STS\webtempSTS.xml
When creating the DDF file, take the following notes into account:
- The instruction
.Set CabinetNameTemplate=MySolution.wsp
is defining the name of the package to be generated. - The instruction
.Set DiskDirectory1=Package
is defining the destination folder where the generated package will be placed. - The instructions
.Set DestinationDir=FolderName
specify that the files listed below it, will be placed inside that folder, in the package. This allows you to compose any internal folder structure, even if the original files are not physically stored with that structure. - Lines that start with the semi-colon (
;
) are comments.
After creating this file, save it with the .ddf
extension (with the name solution.ddf
for instance) in the same folder where you placed the solution manifest (this will be the root folder of the solution package).
Building the Solution Package
Building the solution package is the final and easier part. Just open a command line prompt, and run the following command in the same folder where the DDF file is:
makecab /f solution.ddf
Assuming that your DDF file is named solution.ddf
, this will create a subfolder named Package
and place a MySolution.wsp
file inside it.
Solution Management
Adding a Solution
Adding a solution to SharePoint can only be executed from the command line, using the stsadm tool. You should copy the .wsp
file to the SharePoint server that hosts the Central Administration web application and run the following command:
stsadm -o addsolution -filename MySolution.wsp
This adds the solution to the Solution Store, but does not deploy its components to the SharePoint servers.
Deploying a Solution
To deploy the solution's components to the SharePoint servers you can use one of two methods. The easier one is accessing the Central Administration web site, go to the Operations
section, and select the Solution Management
option. In the Solution Management
screen you will see all the solutions that were added to the Solution Store, and their current state. Clicking the name of the solution you just added, you will have the option to deploy it immediately or at a scheduled time.
The other method is also using the stsadm
command line tool. You can run the following command in the server that hosts the Central Administrator web site:
stsadm -o deploysolution -name MySolution.wsp -immediate -allcontenturls
This command creates a deployment timer job (which executes immediately), that will deploy the solution to all the servers in the farm, and all web applications in SharePoint. This command allows some additional options, that might be necessary depending on the contents of the solution package:
- If the solution contains assemblies that must be placed in the GAC, you must specify the option
-allowgacdeployment
(or-allowgac
for short). - If you have a single-server farm, you can execute the deployment without creating a timer job, changing the
-immediate
option for the-local
option. Note that this means that the contents will not be propagated to additional servers in a multiple-server farm. - You can also specify a time for the deployment to take place, replacing the
-immediate
option for the-time <time to deploy>
option. - If you wish to deploy a solution to a specific web application, rather than to all the web applications (present and future), you must remove the
-allcontenturls
option and add the-url http://webapplicationurl:port
option. - The
-allcontenturls
or-url
options can only be used if the solution contains at least one component that is web application-specific. Examples of such components are:- Assemblies that must be copies to the
BIN
folder of a web application. - Assemblies that must be added to the Safe Controls section of a web applications
web.config
file. - Application resource files specified through the
<ApplicationResourceFiles>
element.
- Assemblies that must be copies to the
- If the solution contains Code Access Security policies, you must specify the
-allowcaspolicies
option.
Retracting a Solution
Retracting a solution is the opposite action of the deployment of the solution. It removes all the components included in the solution (except objects that are in use, such as site columns, site content types or lists) from the SharePoint web sites, but does not remove the solution from the Solution Store.
Like in deployment, you can retract a solution accessing the Central Administration web site, going to the Operations
section and selecting the Solution Management
option. In the Solution Management
screen, clicking on the solution's name will allow you to retract it (if it is deployed) completely or partially (from a specific web application) and schedule a time for the retraction process.
You can also perform these actions through the stsadm
command line tool, executing the following command in the machine that hosts the Central Administrator web site:
stsadm -o retractsolution -name MySolution.wsp -immediate -allcontenturls
This command creates a timer job that will run immediately and retract the solution's components from all the web application in SharePoint. Like in the deploy operation, there are some additional options that can be specified:
- If you have a single-server farm, you can execute the retract without creating a timer job, changing the
-immediate
option for the-local
option. Note that this means that the contents will not be retracted from additional servers in a multiple-server farm. - You can also specify a time for the retraction to take place, replacing the
-immediate
option for the-time <time to retract>
option. - If you wish to retract a solution from a specific web application, rather than to all the web applications, you must remove the
-allcontenturls
option and add the-url http://webapplicationurl:port
option. - The
-allcontenturls
or-url
options can only be used if the solution contains at least one component that is web application-specific. Examples of such components are:- Assemblies that must be copies to the
BIN
folder of a web application. - Assemblies that must be added to the Safe Controls section of a web applications
web.config
file. - Application resource files specified through the
<ApplicationResourceFiles>
element.
- Assemblies that must be copies to the
Deleting a Solution
Deleting a solution from the Solution Store is just as easy as adding it. You can do it using the Central Administration web site, going to the Operations
section and choosing the Solution Management
option. In the Solution Management
screen, if you click the solution's name you will be presented with the option of deleting it from the Solution Store (if the solution is not deployed to any web application).
Additionally, you can use the stsadm
command line tool to do the same, executing the following command:
stsadm -o deletesolution -name MySolution.wsp
Upgrading a Solution
There is an additional and very important action that you can perform on a solution package, and that is upgrading it. When you upgrade a solution, SharePoint compares the new version with the older version and upgrades all the components, without deactivating any features (even if their elements have been updated).
The solution upgrade can only be performed using the stsadm
command line tool, using the following command:
stsadm -o upgradesolution -name <Solution Name> -filename <New Solution File> -immediate
This command creates a timer job that executes immediately and upgrades an existing (and deployed) solution with a new version of itself, packed in a new .wsp
file. Like the deploy and retract operations, the upgrade operation has additional options that might be considered:
- If you have a single-server farm, you can execute the upgrade without creating a timer job, changing the
-immediate
option for the-local
option. Note that this means that the contents will not be upgrade on additional servers in a multiple-server farm. - You can also specify a time for the upgrade operation to take place, replacing the
-immediate
option for the-time <time to upgrade>
option. - If the solution contains assemblies that must be placed in the GAC, you must specify the option
-allowgacdeployment
(or-allowgac
for short). - If the solution contains Code Access Security policies, you must specify the
-allowcaspolicies
option.
Helper Tools
There are several tools that can help you create solutions (and features). Check the following links for some of them:
- Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions (version 1.1)
- SharePoint Installer
- SharePoint 2007 Content Types Viewer
- SharePoint Visual Studio Project Templates
- SharePoint Builder
- STSDEV: Simple Tools for SharePoint 2007 Development
- WSP Builder
- WSP Project Template for Visual Studio
- Solution Pack Generator
- SharePoint Feature Packager
- Solution Installer
- Solution Uploader
- Power Archiver Command Line (thanks to Luís Martins for the tip on this free tool that allows you to generate the CAB file without having to create the DDF file)