A while back I had a solution that would just not be removed. In the Solution Management screen in Central Administration, the Status for the solution was a bright red "Error". Attempting to remove it from there would give an error.
Luckily, I found a great post by Alex Thissen that clearly explains how to use stsadm to remove a malfunctioning solution. The blog post is called Remove malfunctioning Windows SharePoint Services solutions.
In a nutshell, if retracting the solution:
stsadm -o retractsolution -name solutionname.wsp -immediate
doesn't work, and if deleting the solution:
stsadm -o deletesolution -name solutionname.wsp -override
doesn't work, then
1. run an enumeration to see the scheduled deployments
stsadm -o enumdeployments
2. use the JobId to cancel the deployment
stsadm -o canceldeployment -id 2529c788-971c-46a3-b69f-a2a0a1fcc851
Afterwards, you can verify it by doing 1. again.
Showing posts with label solution. Show all posts
Showing posts with label solution. Show all posts
Wednesday, September 28, 2011
Wednesday, June 9, 2010
Update 12 Hive Through A Feature
As we got our SharePoint environment up and running, we needed to have the ability to make changes to our 12-Hive. We also wanted to have the flexibility to undo the changes and restore the 12-Hive to the way it was originally.
This post discusses the scenario where you need to make changes to files that already exist in the 12-Hive. I call this solution HiveUpdates. If you have a need to add new files to the 12-Hive that do not already exist, such as new images or layouts, check out my other article Add New Files To 12-Hive Through A Solution. I call that solution HiveAdditions. We decided it would be best for us to separate these two types of Hive changes into two separate solutions.
This solution, HiveUpdates, allows us to modify existing Hive files. This solution contains a feature that, when activated, makes a backup copy of the original file, then overwrites the original with the new file. When the feature is deactivated, it copies the backup file back to the original filename.
The method I used is based on the article 12 Hive System-File Changes: One Feature to rule them all!. The above post has a routine that is called when the feature is activated or when its deactivated. The code that fires simply "swaps" newly changed 12-hive files with their corresponding original 12-hive files. This happens both when the feature is activated or deactivated. While the "swap" code seems like a good idea on the surface (the same code that deploys the changes will swap files back to undeploy them), I found in practice this seemed risky and even prone to error if something went wrong on the feature activate or feature deactivate. I sometimes got the files out of sync and would lose the original 12-Hive versions.
Therefore, I modified the code to first make a backup copy of a 12-Hive file I want to update, then overwrite the original 12-hive file with my changed version (this is an activate). On a deactivate, it overwrites my changed version with the original's backup file. The original's backup file always stays there as a backup, which makes me feel very safe. And I like feeling safe. I like my job and want to keep it.
1. In Visual Studio 2008, File -> New -> Project
2. Under Visual C#, pick SharePoint, then Empty
3. For Name, type: HiveUpdates
4. For Location, type: D:\development
5. Click OK
6. Select Full Trust (Deploy to GAC) and click OK
7. In WSP View (View -> Other Windows -> WSP View), click "Create new feature"
8. Change Feature Scope to Farm
9. Check Add feature receiver
10. click OK
11. In Solution Explorer, rename Feature1 to HiveUpdates
12. Rename Feature1Receiver.cs to HiveUpdatesReceiver.cs
13. Double-click HiveUpdatesReceiver.cs to open it
14. Rename class from FeatureReceiver1 to HiveUpdatesReceiver
15. Below that, you'll see the constructor "public FeatureReceiver1". Rename constructor from FeatureReceiver1 to HiveUpdatesReceiver.
16. In WSP View, hit refresh and notice FeatureReceiver1 is now HiveUpdatesReceiver
17. Rename Feature1 folder to HiveUpdates
Make the following code modifications/additions to HiveUpdatesReceiver.cs:
18. At the top of the code, add the following using statements:
19. Above the HiveUpdatesReceiver constructor, add the following:
20. In the FeatureActivated method, add:
21. In the FeatureDeactivating method, add:
22. Below the FeatureUninstalling method, add the following 4 methods (DeployToHive, RemoveFromHive, GetHiveFile, GetLocalDirectory):
Now we need to create the appropriate 12-Hive file structure for the feature in Solution Explorer. Any 12-Hive files we want to update will have their newer versions placed in the file structure we are about to create.
23. In Solution Explorer, right-click project HiveUpdates, then click Add -> New Item... -> SharePoint -> Template.
24. You will notice a folder called Templates was created in the Solution Explorer. Delete the default file TemplateFile1.txt.
25. Under Templates, create a folder called FEATURES.
26. Under FEATURES, create a folder called HiveUpdates.
So far, we have created 12/TEMPLATE/FEATURES/HiveUpdates. This is the location in the 12-Hive where that feature's feature.xml gets deployed to. But now, we must create another 12-Hive structure under this folder. This is where our newer files will be deployed to when the solution is initially deployed. When the feature is activated, this is where the above code will store backups of the original files from the 12-Hive, as well as the source from which to overwrite the 12-Hive files with.
27. Under HiveUpdates, create a folder called 12.
28. Under 12, create a folder called TEMPLATE.
29. Under TEMPLATE, create a folder called LAYOUTS.
30. Copy application.master in here. Either make some small change to it or at the very least change the date on the file so its different from what it is in the 12-Hive. Be sure to right-click application.master and click Include In Project if it is not already included.
31. In WSP View, double-click feature.xml.
32. Change the value of Title from Feature1 to HiveUpdates.
33. Verify Scope is set to Farm.
33. After the title or scope, add: ActivateOnDefault="false"
34. Verify your manifest was created correctly. In WSP View, Under HiveUpdates, you should see manifest.xml. Double-click manifest.xml and verify your file path for application.master is FEATURES\HiveUpdates\12\TEMPLATE\LAYOUTS.
35. click Build -> Rebuild Solution
36. click Build -> Package Solution
The solution package that you just created in the above step, HiveUpdates.wsp, was created in your project's bin\debug folder.
To deploy the solution:
37. create folder d:\deploy
38. copy HiveUpdates.wsp from project's bin\debug folder to d:\deploy
39. In d:\deploy, create two batch files, add_hiveupdates.bat and remove_hiveupdates.bat.
add_hiveupdates.bat:
remove_hiveupdates.bat:
40. in d:\deploy, type add_hiveupdates.wsp and hit enter
41. verify solution was deployed in Central Administration -> Operations -> Solution Management
42. verify files were added to 12-Hive!
This post discusses the scenario where you need to make changes to files that already exist in the 12-Hive. I call this solution HiveUpdates. If you have a need to add new files to the 12-Hive that do not already exist, such as new images or layouts, check out my other article Add New Files To 12-Hive Through A Solution. I call that solution HiveAdditions. We decided it would be best for us to separate these two types of Hive changes into two separate solutions.
This solution, HiveUpdates, allows us to modify existing Hive files. This solution contains a feature that, when activated, makes a backup copy of the original file, then overwrites the original with the new file. When the feature is deactivated, it copies the backup file back to the original filename.
The method I used is based on the article 12 Hive System-File Changes: One Feature to rule them all!. The above post has a routine that is called when the feature is activated or when its deactivated. The code that fires simply "swaps" newly changed 12-hive files with their corresponding original 12-hive files. This happens both when the feature is activated or deactivated. While the "swap" code seems like a good idea on the surface (the same code that deploys the changes will swap files back to undeploy them), I found in practice this seemed risky and even prone to error if something went wrong on the feature activate or feature deactivate. I sometimes got the files out of sync and would lose the original 12-Hive versions.
Therefore, I modified the code to first make a backup copy of a 12-Hive file I want to update, then overwrite the original 12-hive file with my changed version (this is an activate). On a deactivate, it overwrites my changed version with the original's backup file. The original's backup file always stays there as a backup, which makes me feel very safe. And I like feeling safe. I like my job and want to keep it.
1. In Visual Studio 2008, File -> New -> Project
2. Under Visual C#, pick SharePoint, then Empty
3. For Name, type: HiveUpdates
4. For Location, type: D:\development
5. Click OK
6. Select Full Trust (Deploy to GAC) and click OK
7. In WSP View (View -> Other Windows -> WSP View), click "Create new feature"
8. Change Feature Scope to Farm
9. Check Add feature receiver
10. click OK
11. In Solution Explorer, rename Feature1 to HiveUpdates
12. Rename Feature1Receiver.cs to HiveUpdatesReceiver.cs
13. Double-click HiveUpdatesReceiver.cs to open it
14. Rename class from FeatureReceiver1 to HiveUpdatesReceiver
15. Below that, you'll see the constructor "public FeatureReceiver1". Rename constructor from FeatureReceiver1 to HiveUpdatesReceiver.
16. In WSP View, hit refresh and notice FeatureReceiver1 is now HiveUpdatesReceiver
17. Rename Feature1 folder to HiveUpdates
Make the following code modifications/additions to HiveUpdatesReceiver.cs:
18. At the top of the code, add the following using statements:
using Microsoft.SharePoint.Administration;
using System.IO;
using System.IO;
19. Above the HiveUpdatesReceiver constructor, add the following:
private DirectoryInfo localDirectory = new DirectoryInfo(@"C:\");
20. In the FeatureActivated method, add:
DeployToHive(properties);
21. In the FeatureDeactivating method, add:
RemoveFromHive(properties);
22. Below the FeatureUninstalling method, add the following 4 methods (DeployToHive, RemoveFromHive, GetHiveFile, GetLocalDirectory):
private void DeployToHive(SPFeatureReceiverProperties properties)
{
//loop through each server in the farm
foreach (SPServer server in properties.Definition.Farm.Servers)
{
//if the current server is a WebFrontEnd server
if (server.Role == SPServerRole.WebFrontEnd || server.Role == SPServerRole.Application
|| server.Role == SPServerRole.SingleServer)
{
string localFilePath = GetLocalDirectory(properties.Definition.RootDirectory,
server.Name);
localDirectory = new DirectoryInfo(localFilePath);
foreach (FileInfo fileinfo in localDirectory.GetFiles("*",
SearchOption.AllDirectories))
{
//if current file in feature exists in 12 hive on current server
if (File.Exists(GetHiveFile(fileinfo.FullName, server.Name))
&& (!fileinfo.FullName.Contains(".hivebackup")))
// backup file from 12 hive to feature
File.Copy(GetHiveFile(fileinfo.FullName, server.Name),
fileinfo.FullName + ".hivebackup", true);
//if current file in feature exists
if (File.Exists(fileinfo.FullName) &&
(!fileinfo.FullName.Contains(".hivebackup")))
// copy local file to the 12 hive
File.Copy(fileinfo.FullName, GetHiveFile(fileinfo.FullName, server.Name),
true);
}
}
}
}
private void RemoveFromHive(SPFeatureReceiverProperties properties)
{
//loop through each server in the farm
foreach (SPServer server in properties.Definition.Farm.Servers)
{
//if the current server is a WebFrontEnd server
if (server.Role == SPServerRole.WebFrontEnd
|| server.Role == SPServerRole.Application
|| server.Role == SPServerRole.SingleServer)
{
string localFilePath = GetLocalDirectory(properties.Definition.RootDirectory,
server.Name);
localDirectory = new DirectoryInfo(localFilePath);
foreach (FileInfo fileinfo in localDirectory.GetFiles("*",
SearchOption.AllDirectories))
{
//if current backup file in feature exists in 12 hive
if (File.Exists(fileinfo.FullName + ".hivebackup"))
// copy hivebackup file back to the 12 hive
File.Copy(fileinfo.FullName + ".hivebackup",
GetHiveFile(fileinfo.FullName, server.Name), true);
}
}
}
}
string GetHiveFile(string fileName, string serverName)
{
if (fileName.StartsWith(localDirectory.FullName))
{ // file is local
string p = @"\\" + serverName
+ @"\C$\Program Files\Common Files\Microsoft Shared\web server extensions\12"
+ fileName.Remove(0, localDirectory.FullName.Length);
return p;
}
throw new Exception("Filepath doesn't point to correct local hive!");
}
string GetLocalDirectory(string filePath, string serverName)
{
return @"\\" + serverName + @"\" + @filePath.Replace(":", "$") + @"\12";
//write a class that writes exceptions to the event log
throw new Exception("Filepath doesn't point to correct local hive!");
}
Now we need to create the appropriate 12-Hive file structure for the feature in Solution Explorer. Any 12-Hive files we want to update will have their newer versions placed in the file structure we are about to create.
23. In Solution Explorer, right-click project HiveUpdates, then click Add -> New Item... -> SharePoint -> Template.
24. You will notice a folder called Templates was created in the Solution Explorer. Delete the default file TemplateFile1.txt.
25. Under Templates, create a folder called FEATURES.
26. Under FEATURES, create a folder called HiveUpdates.
So far, we have created 12/TEMPLATE/FEATURES/HiveUpdates. This is the location in the 12-Hive where that feature's feature.xml gets deployed to. But now, we must create another 12-Hive structure under this folder. This is where our newer files will be deployed to when the solution is initially deployed. When the feature is activated, this is where the above code will store backups of the original files from the 12-Hive, as well as the source from which to overwrite the 12-Hive files with.
27. Under HiveUpdates, create a folder called 12.
28. Under 12, create a folder called TEMPLATE.
29. Under TEMPLATE, create a folder called LAYOUTS.
30. Copy application.master in here. Either make some small change to it or at the very least change the date on the file so its different from what it is in the 12-Hive. Be sure to right-click application.master and click Include In Project if it is not already included.
31. In WSP View, double-click feature.xml.
32. Change the value of Title from Feature1 to HiveUpdates.
33. Verify Scope is set to Farm.
33. After the title or scope, add: ActivateOnDefault="false"
34. Verify your manifest was created correctly. In WSP View, Under HiveUpdates, you should see manifest.xml. Double-click manifest.xml and verify your file path for application.master is FEATURES\HiveUpdates\12\TEMPLATE\LAYOUTS.
35. click Build -> Rebuild Solution
36. click Build -> Package Solution
The solution package that you just created in the above step, HiveUpdates.wsp, was created in your project's bin\debug folder.
To deploy the solution:
37. create folder d:\deploy
38. copy HiveUpdates.wsp from project's bin\debug folder to d:\deploy
39. In d:\deploy, create two batch files, add_hiveupdates.bat and remove_hiveupdates.bat.
add_hiveupdates.bat:
c:
cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o addsolution -filename d:\deploy\HiveUpdates\HiveUpdates.wsp
stsadm -o deploysolution -name HiveUpdates.wsp -immediate -allowGacDeployment
pause
stsadm -o activatefeature -name HiveUpdates
d:
cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o addsolution -filename d:\deploy\HiveUpdates\HiveUpdates.wsp
stsadm -o deploysolution -name HiveUpdates.wsp -immediate -allowGacDeployment
pause
stsadm -o activatefeature -name HiveUpdates
d:
remove_hiveupdates.bat:
c:
cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o deactivatefeature -name HiveUpdates
stsadm -o retractsolution -name HiveUpdates.wsp -immediate
pause
stsadm -o deletesolution -name HiveUpdates.wsp
d:
cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o deactivatefeature -name HiveUpdates
stsadm -o retractsolution -name HiveUpdates.wsp -immediate
pause
stsadm -o deletesolution -name HiveUpdates.wsp
d:
40. in d:\deploy, type add_hiveupdates.wsp and hit enter
41. verify solution was deployed in Central Administration -> Operations -> Solution Management
42. verify files were added to 12-Hive!
Tags:
feature,
sharepoint,
solution,
update 12-hive
Saturday, June 5, 2010
Add New Files To 12-Hive Through A SharePoint Solution
As we got our SharePoint environment up and running, we needed to have the ability to make changes to our 12-Hive. We also wanted to have the flexibility to undo the changes and restore the 12-Hive to the way it was originally.
This post discusses the scenario where you need to add new files to the 12-Hive that do not already exist, such as new images or layouts. I call this solution HiveAdditions. If you have a need to update files that already exist in the 12-Hive, check out my other article Update 12 Hive Through A Feature. I call that solution HiveUpdates. We decided it would be best for us to separate these two types of Hive changes into two separate solutions.
This solution, HiveAdditions, simply allows us to add files into the 12-Hive upon a deployment. When we retract this solution, it simply removes all those files. We liked this approach because it allows us to have this solution as the one place for all new 12-Hive files. If we needed to add new files, we retract this solution, add the new files to the solution, then deploy it again.
1. In Visual Studio 2008, File -> New -> Project
2. Under Visual C#, pick SharePoint, then Empty
3. For Name, type: HiveAdditions
4. For Location, type: D:\development
5. Click OK
6. Select Full Trust (Deploy to GAC) and click OK
7. In Solution Explorer, right-click project HiveAdditions, then click Add -> New Items... -> SharePoint -> Root File
8. Leave Name alone and click Add
9. Under RootFiles (which now appears in Solution Explorer), delete RootFile1
Under RootFiles, we must mirror the 12-Hive locations where we want to add the new files.
Let's add image files under TEMPLATE/IMAGES.
10. Right-click RootFiles, click Add -> New Folder and name it TEMPLATE.
11. Right-click TEMPLATE, click Add -> New Folder and name it IMAGES.
12. Drag and drop your images into IMAGES folder. Be sure to right-click newly added files and click Include In Project if they are not already included.
13. Verify your manifest was created correctly. Click View -> Other Windows -> WSP View. Under HiveAdditions, you should see manifest.xml, then under that, RootFiles -> TEMPLATE -> IMAGES followed by the files you added. Double-click manifest.xml and verify your file paths are under TEMPLATE\IMAGES\file1.jpg, etc.
14. click Build -> Rebuild Solution
15. click Build -> Package Solution
The solution package that you just created in the above step, HiveAdditions.wsp, was created in your project's bin\debug folder.
To deploy the solution:
16. create folder d:\deploy
17. copy HiveAdditions.wsp from project's bin\debug folder to d:\deploy
18. In d:\deploy, create two batch files, add_hiveadditions.bat and remove_hiveadditions.bat.
add_hiveadditions.bat:
20. verify solution was deployed in Central Administration -> Operations -> Solution Management
21. verify files were added to 12-Hive!
This post discusses the scenario where you need to add new files to the 12-Hive that do not already exist, such as new images or layouts. I call this solution HiveAdditions. If you have a need to update files that already exist in the 12-Hive, check out my other article Update 12 Hive Through A Feature. I call that solution HiveUpdates. We decided it would be best for us to separate these two types of Hive changes into two separate solutions.
This solution, HiveAdditions, simply allows us to add files into the 12-Hive upon a deployment. When we retract this solution, it simply removes all those files. We liked this approach because it allows us to have this solution as the one place for all new 12-Hive files. If we needed to add new files, we retract this solution, add the new files to the solution, then deploy it again.
1. In Visual Studio 2008, File -> New -> Project
2. Under Visual C#, pick SharePoint, then Empty
3. For Name, type: HiveAdditions
4. For Location, type: D:\development
5. Click OK
6. Select Full Trust (Deploy to GAC) and click OK
7. In Solution Explorer, right-click project HiveAdditions, then click Add -> New Items... -> SharePoint -> Root File
8. Leave Name alone and click Add
9. Under RootFiles (which now appears in Solution Explorer), delete RootFile1
Under RootFiles, we must mirror the 12-Hive locations where we want to add the new files.
Let's add image files under TEMPLATE/IMAGES.
10. Right-click RootFiles, click Add -> New Folder and name it TEMPLATE.
11. Right-click TEMPLATE, click Add -> New Folder and name it IMAGES.
12. Drag and drop your images into IMAGES folder. Be sure to right-click newly added files and click Include In Project if they are not already included.
13. Verify your manifest was created correctly. Click View -> Other Windows -> WSP View. Under HiveAdditions, you should see manifest.xml, then under that, RootFiles -> TEMPLATE -> IMAGES followed by the files you added. Double-click manifest.xml and verify your file paths are under TEMPLATE\IMAGES\file1.jpg, etc.
14. click Build -> Rebuild Solution
15. click Build -> Package Solution
The solution package that you just created in the above step, HiveAdditions.wsp, was created in your project's bin\debug folder.
To deploy the solution:
16. create folder d:\deploy
17. copy HiveAdditions.wsp from project's bin\debug folder to d:\deploy
18. In d:\deploy, create two batch files, add_hiveadditions.bat and remove_hiveadditions.bat.
add_hiveadditions.bat:
c:
cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o addsolution -filename d:\deploy\HiveAdditions\HiveAdditions.wsp
stsadm -o deploysolution -name HiveAdditions.wsp -immediate -allowGacDeployment
d:
remove_hiveadditions.bat:cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o addsolution -filename d:\deploy\HiveAdditions\HiveAdditions.wsp
stsadm -o deploysolution -name HiveAdditions.wsp -immediate -allowGacDeployment
d:
c:
cd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o retractsolution -name HiveAdditions.wsp -immediate
pause
stsadm -o deletesolution -name HiveAdditions.wsp
d:
19. in d:\deploy, type add_hiveadditions.wsp and hit entercd\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN
stsadm -o retractsolution -name HiveAdditions.wsp -immediate
pause
stsadm -o deletesolution -name HiveAdditions.wsp
d:
20. verify solution was deployed in Central Administration -> Operations -> Solution Management
21. verify files were added to 12-Hive!
Tags:
solution,
update 12-hive
Thursday, July 23, 2009
How to deploy a SharePoint web part to bin
As I was learning how to deploy my web parts as features in a solution package .wsp (I used WSPBuilder to create the .wsp), I realized I needed to make sure they were deployed not to the GAC (which is the default), but rather to the web application's /bin folder (under the web application in IIS). Bin is preferred over GAC because of security reasons: deploying to GAC unnecessarily exposes the web part's assembly .dll to every application on the server.
This post will show you how to deploy a web part to the /bin folder (using WSPBuilder) AND how to configure it using CAS (Code Access Security) so your web part can actually run from that folder too! I kept finding articles that discuss one or the other, but not both. Those articles that did help me quite a bit have been referenced in the last part of this post.
So, from the top, when you create a web part in Visual Studio 2008 and hit F5, the web part will deploy to the site you selected (right-click Project's Properties, click Debug, then whatever site you typed in Start browser with URL). In your Solution Explorer, you will notice a folder called /bin with another folder called /debug under that, and the compiled code will sit under there. This means its being deployed into the GAC.
At a high level, there's really two steps we must do to get our web part to run from the web application's (your SharePoint site's) /bin folder. (You can get to /bin either by going into IIS and choosing the web application you want it deployed to, or by going to c:\inetpub\wwwroot\wss\VirtualDirectories\<web application>\bin.)
The first step is actually deploying to the above-mentioned location. Once this is done, sure, the web part is right where you want it to be, but it won't run until we do step two, which involves setting the proper permissions to allow it to run from that spot. This second step involves modifying the web.config to look at a custom policy file where we will make changes to the CAS policies.
1. In Solution Explorer, delete the /bin folder. It will reappear in a few seconds with a Debug subfolder, but it will be empty other than that.
2. In Solution Explorer, create a folder called 80, and under that, create a folder called bin. So you will have /80/bin.
3. Right-click the project in Solution Explorer, and on the Compile tab, change Build Output Path from bin\Debug\ to 80\bin\.
4. In Solution Explorer, in AssemblyInfo.vb, you must add two lines:
a. below the other Imports statements, add the following:
b. Below one of the other Assembly statements, add the following:
5. Now, when you compile the application you will notice the assembly (the dll) appears in /80/bin instead of where it was being put before, /bin/debug. If you hit F5 to deploy it, you will notice all the other deployment files Visual Studio creates is also placed in this folder. This leads me to my next point.
Visual Studio creating deployment files automatically is no good. Sure, it will get everything up and running on the server, but maybe not the way you want. For instance, even though I have created a /12/TEMPLATE/FEATURES/AddContactFromAD folder structure in my Solution Explorer, and put in my feature.xml, elements.xml (mine is actually called AddContactFromAD.xml), and a web part definitions file AddContactFromAD.webpart, Visual Studio generates its own feature.xml (which doesn't have my pretty description I put in the real feature.xml). It also tends to write its own manifest.xml, wanting to deploy to GAC! So, let's deploy a much better way, using WSPBuilder! You can download WSPBuilder here. Once installed, it will be added to Visual Studio's Tools menu.
6. Assuming you have the above-mentioned 12 hive folder structure with a folder for each web part under FEATURES, and with that, a feature.xml, elements.xml, and .webpart file under each web part's folder, you can simply click Tools -> WSPBuilder -> Build WSP. WSP Builder will create the resulting .wsp and drop it in your project folder. Renaming it to .cab and opening it you will see each web part's feature.xml, elements.xml, .webpart, plus the assembly .dll and an autogenerated manifest.xml. Looking inside the manifest.xml will reveal two things: 1. the DeploymentTarget is WebApplication (no longer GlobalAssemblyCache as it was before), and 2. CAS policy permissions were added.
7. Ok, so let's deploy this bad boy. To do this, I add the solution, deploy the solution, then activate the features (1 feature per web part). Below is my own batch file add.bat:
Also, my remove.bat comes in handy when testing:
At this point, if you check your web application's /bin, you should see the assembly .dll there. If you go to the Web Part Gallery and click the web part, or if you attempt to add the web part to a page, you will get an error. This is because we still need to do Part 2 of this grand adventure: modify the permissions.
1. We are going to copy the existing wss_minimaltrust.config, rename it, then make our policy changes in that file. Go to c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG, copy wss_minimaltrust.config and rename it wss_webpartbintrust.config.
2. In our new CAS policy file, wss_webpartbintrust.config, we have three changes.
a. First, add a reference to SharePointPermission in the <SecurityClasses> section. Add the following:
b. Next, add a new custom permission set. Find the NamedPermissionSet that is named SPRestricted and copy and paste this below it:
c. Finally, add the code group. This will indicate when the permissions are to be set. It should be noted this can be done one of two ways, either using a strong name membership (assuming your assembly has been strongnamed) or a url membership, which would give you the option of having the permissions apply to all assemblies in the specified bin or the specific assembly itself.
Under <CodeGroup class="FirstMatchCodeGroup"...> you will see several <CodeGroup class="UnionCodeGroup"...> tags. Place the following code as the first one of these.
3. Almost there... Just two more changes, but this time in your site's web.config. Go to c:\inetpub\wwwroot\wss\VirtualDirectories\<your site>\web.config.
a. In the SecurityPolicy tag, make sure there is an entry for a custom TrustLevel that points to the policy file we just edited:
b. Scroll down a bit and make sure the trust level is set like this:
That's it! Restart IIS and have fun!
Some good pages that helped me figure this all out:
WSPBuilder - Walkthrough of the Visual Studio Add-in
MOSS 2007 and Code Access Security
Gaurav Taneja article on bin and GAC deployment
Deploy dlls to the webApplications bin rather than GAC
Code Access Security in SharePoint 2007 for Administrators
This post will show you how to deploy a web part to the /bin folder (using WSPBuilder) AND how to configure it using CAS (Code Access Security) so your web part can actually run from that folder too! I kept finding articles that discuss one or the other, but not both. Those articles that did help me quite a bit have been referenced in the last part of this post.
So, from the top, when you create a web part in Visual Studio 2008 and hit F5, the web part will deploy to the site you selected (right-click Project's Properties, click Debug, then whatever site you typed in Start browser with URL). In your Solution Explorer, you will notice a folder called /bin with another folder called /debug under that, and the compiled code will sit under there. This means its being deployed into the GAC.
At a high level, there's really two steps we must do to get our web part to run from the web application's (your SharePoint site's) /bin folder. (You can get to /bin either by going into IIS and choosing the web application you want it deployed to, or by going to c:\inetpub\wwwroot\wss\VirtualDirectories\<web application>\bin.)
The first step is actually deploying to the above-mentioned location. Once this is done, sure, the web part is right where you want it to be, but it won't run until we do step two, which involves setting the proper permissions to allow it to run from that spot. This second step involves modifying the web.config to look at a custom policy file where we will make changes to the CAS policies.
First, deploy the web part assembly to the /bin:
1. In Solution Explorer, delete the /bin folder. It will reappear in a few seconds with a Debug subfolder, but it will be empty other than that.
2. In Solution Explorer, create a folder called 80, and under that, create a folder called bin. So you will have /80/bin.
3. Right-click the project in Solution Explorer, and on the Compile tab, change Build Output Path from bin\Debug\ to 80\bin\.
4. In Solution Explorer, in AssemblyInfo.vb, you must add two lines:
a. below the other Imports statements, add the following:
Imports System.Security
(Note: this will be a Using statement if you are doing C#)b. Below one of the other Assembly statements, add the following:
<assembly: AllowPartiallyTrustedCallers()>
(Note: This step doesn't affect the deployment of the web part, but comes into play when you try to actually use the web part on a page after its been deployed to /bin.)5. Now, when you compile the application you will notice the assembly (the dll) appears in /80/bin instead of where it was being put before, /bin/debug. If you hit F5 to deploy it, you will notice all the other deployment files Visual Studio creates is also placed in this folder. This leads me to my next point.
Visual Studio creating deployment files automatically is no good. Sure, it will get everything up and running on the server, but maybe not the way you want. For instance, even though I have created a /12/TEMPLATE/FEATURES/AddContactFromAD folder structure in my Solution Explorer, and put in my feature.xml, elements.xml (mine is actually called AddContactFromAD.xml), and a web part definitions file AddContactFromAD.webpart, Visual Studio generates its own feature.xml (which doesn't have my pretty description I put in the real feature.xml). It also tends to write its own manifest.xml, wanting to deploy to GAC! So, let's deploy a much better way, using WSPBuilder! You can download WSPBuilder here. Once installed, it will be added to Visual Studio's Tools menu.
6. Assuming you have the above-mentioned 12 hive folder structure with a folder for each web part under FEATURES, and with that, a feature.xml, elements.xml, and .webpart file under each web part's folder, you can simply click Tools -> WSPBuilder -> Build WSP. WSP Builder will create the resulting .wsp and drop it in your project folder. Renaming it to .cab and opening it you will see each web part's feature.xml, elements.xml, .webpart, plus the assembly .dll and an autogenerated manifest.xml. Looking inside the manifest.xml will reveal two things: 1. the DeploymentTarget is WebApplication (no longer GlobalAssemblyCache as it was before), and 2. CAS policy permissions were added.
7. Ok, so let's deploy this bad boy. To do this, I add the solution, deploy the solution, then activate the features (1 feature per web part). Below is my own batch file add.bat:
stsadm -o addsolution -filename contactuswebpart.wsp
stsadm -o deploysolution -name contactuswebpart.wsp -url http://sharepoint2007:1001/ -immediate -allowCasPolicies
stsadm -o activatefeature -name contactlist -url http://sharepoint2007:1001
stsadm -o activatefeature -name emailcontact -url http://sharepoint2007:1001
stsadm -o activatefeature -name addcontactfromad -url http://sharepoint2007:1001
stsadm -o deploysolution -name contactuswebpart.wsp -url http://sharepoint2007:1001/ -immediate -allowCasPolicies
stsadm -o activatefeature -name contactlist -url http://sharepoint2007:1001
stsadm -o activatefeature -name emailcontact -url http://sharepoint2007:1001
stsadm -o activatefeature -name addcontactfromad -url http://sharepoint2007:1001
Also, my remove.bat comes in handy when testing:
stsadm -o deactivatefeature -name contactlist -url http://sharepoint2007:1001
stsadm -o deactivatefeature -name emailcontact -url http://sharepoint2007:1001
stsadm -o deactivatefeature -name addcontactfromad -url http://sharepoint2007:1001
stsadm -o retractsolution -name contactuswebpart.wsp -url http://sharepoint2007:1001/ -immediate
stsadm -o deletesolution -name contactuswebpart.wsp
stsadm -o deactivatefeature -name emailcontact -url http://sharepoint2007:1001
stsadm -o deactivatefeature -name addcontactfromad -url http://sharepoint2007:1001
stsadm -o retractsolution -name contactuswebpart.wsp -url http://sharepoint2007:1001/ -immediate
stsadm -o deletesolution -name contactuswebpart.wsp
At this point, if you check your web application's /bin, you should see the assembly .dll there. If you go to the Web Part Gallery and click the web part, or if you attempt to add the web part to a page, you will get an error. This is because we still need to do Part 2 of this grand adventure: modify the permissions.
For the second and final step, set the CAS policy permissions to enable the web part to run from /bin:
1. We are going to copy the existing wss_minimaltrust.config, rename it, then make our policy changes in that file. Go to c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG, copy wss_minimaltrust.config and rename it wss_webpartbintrust.config.
2. In our new CAS policy file, wss_webpartbintrust.config, we have three changes.
a. First, add a reference to SharePointPermission in the <SecurityClasses> section. Add the following:
<SecurityClass Name="SharePointPermission" Description="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
b. Next, add a new custom permission set. Find the NamedPermissionSet that is named SPRestricted and copy and paste this below it:
<PermissionSet class="NamedPermissionSet" version="1" Name="WebPartBinTrust">
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="WebPartPermission" version="1" Connections="True" />
<IPermission class="SharePointPermission" version="1" ObjectModel="True" />
</PermissionSet>
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="WebPartPermission" version="1" Connections="True" />
<IPermission class="SharePointPermission" version="1" ObjectModel="True" />
</PermissionSet>
c. Finally, add the code group. This will indicate when the permissions are to be set. It should be noted this can be done one of two ways, either using a strong name membership (assuming your assembly has been strongnamed) or a url membership, which would give you the option of having the permissions apply to all assemblies in the specified bin or the specific assembly itself.
Under <CodeGroup class="FirstMatchCodeGroup"...> you will see several <CodeGroup class="UnionCodeGroup"...> tags. Place the following code as the first one of these.
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="WebPartBinTrust">
<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="00240000048000009400000006020000002400005253413100040000010001000DAF8ED8D945CD2ABB2EE7953A6039B791A725F11B4588AC6D70B3E0648F955E9ED4C3C43CB044B8B0E8A6FF4D4FFBE9E3B9297D45F688A7264534E12414E17539305207EC961DA94DF294E7722CCD9BDBFC95A896E996F57156705D281EC39280BD604E87724556AF5807D146963F19F5B43DB69E1F22695463153A553260D2" Name="ContactUsWebPart" />
</CodeGroup>
(Note: The PublicKeyBlob must be the public key blob of your assembly. You may see the PublicKeyBlob in another tag referencing your assembly, in which case, just copy and paste it. Otherwise, you will need to run the command: secutil -hex -s contactuswebpart.dll > publickeyblob.txt, then copy and paste it from the output file publickeyblob.txt.)<IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="00240000048000009400000006020000002400005253413100040000010001000DAF8ED8D945CD2ABB2EE7953A6039B791A725F11B4588AC6D70B3E0648F955E9ED4C3C43CB044B8B0E8A6FF4D4FFBE9E3B9297D45F688A7264534E12414E17539305207EC961DA94DF294E7722CCD9BDBFC95A896E996F57156705D281EC39280BD604E87724556AF5807D146963F19F5B43DB69E1F22695463153A553260D2" Name="ContactUsWebPart" />
</CodeGroup>
3. Almost there... Just two more changes, but this time in your site's web.config. Go to c:\inetpub\wwwroot\wss\VirtualDirectories\<your site>\web.config.
a. In the SecurityPolicy tag, make sure there is an entry for a custom TrustLevel that points to the policy file we just edited:
<trustLevel name="WSS_Custom" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_webpartbintrust.config" />
b. Scroll down a bit and make sure the trust level is set like this:
<trust level="WSS_Custom" originUrl="" />
That's it! Restart IIS and have fun!
Some good pages that helped me figure this all out:
WSPBuilder - Walkthrough of the Visual Studio Add-in
MOSS 2007 and Code Access Security
Gaurav Taneja article on bin and GAC deployment
Deploy dlls to the webApplications bin rather than GAC
Code Access Security in SharePoint 2007 for Administrators
Tags:
deployment,
feature,
solution,
web part,
WSPBuilder
Subscribe to:
Posts (Atom)