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!
No comments:
Post a Comment