A question came up today that I thought was interesting and I hadn’t fully examined before.
If you retract and delete a solution in SharePoint 2007 without first uninstalling its features, are turds left behind?
The short answer: If you retract and delete a solution without deactivating and uninstalling the feature for each deployed scope, then turds are left behind both in the file system and in the config database.
To demonstrate this, I created a simple ItemEventReceiver, which uses a feature that is scoped to the web level. I deploy the solution to a web application, and then it is available to the individual web sites to activate. The code for this is unimportant, it’s just a solution that contains a feature scoped to the web level. Here are the commands that I run to add my solution to the solution store, deploy it to a web application, and activate the feature for a web site within the web application.
stsadm -o addsolution -filename featuretester.wsp stsadm -o deploysolution -name featuretester.wsp -allowGacDeployment -immediate -url http://moss-1 stsadm -o execadmsvcjobs stsadm -o activatefeature -id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1
This is pretty standard stuff. You probably already know that this creates a folder in the SharePoint root for our feature in the 12/Template/Features folder.
This also deploys our assembly to the Global Assembly Cache.
I wonder, though, does the feature exist only in the file system, or is it now part of the configuration database? We check the configuration database, and yep… there’s an entry in the dbo.Features table for our feature.
Let’s see what happens if we activate our feature for a new web.
stsadm -o activatefeature -id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1/sitedirectory/team
As we expected, there are now two entries in the dbo.Features table.
Cleaning It Up The Right Way
Cleaning this up the right way is simple, we reverse all of our steps until now. We need to deactivate the feature for each scope that we activated it for.
stsadm –o deactivatefeature –id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1 stsadm –o deactivatefeature –id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1/sitedirectory/team stsadm –o uninstallfeature –id fb9375d5-07ae-4835-b64c-83441c806691
This will remove the entries from the configuration database and remove the entries from the file system in a supported manner.
What Happens if I Don’t Clean It Up The Right Way?
OK, now our real question. Imagine we are still at the point where everything is deployed and activated. We now have artifacts in the configuration database, and we have artifacts in the file system for every server in our farm. What happens if we retract the solution and delete it? Are turds left behind in the database and file system, or does SharePoint get rid of them for us?
stsadm -o retractsolution -name featuretester.wsp -immediate -url http://moss-1 stsadm -o exeadmsvcjobs stsadm -o deletesolution -name featuretester.wsp
Here, we are retracting the solution from the web application and then deleting the solution from the solution store. Let’s go check our artifacts on the server again to see what remains.
First, we look in the file system. Hmm… the files are still there.
I know what you’re thinking, “so what? they’re just files and folders.” Fair enough, simply adding folders and files to the SharePoint root doesn’t do anything unless we tell SharePoint about it using an stsadm command. Let’s go look at the Global Assembly Cache.
As you can see, the entry for our assembly is no longer in the GAC. When we deleted the solution, the assembly was removed as part of the process (just as it is added when you call addsolution).
OK, so far it left behind files and folders, removed an entry from the GAC… is it clean? Well, no. SharePoint still has pointer records to the features in the configuration database.
At this point you may be thinking, “so what? it left behind turds, but my farm is still running ok.” Effectively, all we did was remove the DLL from the GAC and the WSP from the solution store. The individual web sites still think there’s an ItemEventReceiver deployed. That’s why we find the following types of errors when we go to a list where an ItemEventReceiver was bound
02/02/2011 22:40:54.78 w3wp.exe (0x193C) 0x1EDC Windows SharePoint Services General 75fe High Failed to determine definition for Feature with ID ‘fb9375d5-07ae-4835-b64c-83441c806691′. Skipping this feature for element querying consideration.
What’s happening is that there is a feature that is orphaned because its implementation is missing. It shows up in the ULS log to let us know that it thought there was a feature deployed here, but something’s gone wrong.
Let’s look at one more thing… upgrading. After SP2 for SharePoint 2007, a new command was added to stsadm to check for potential upgrade issues. We run the command:
stsadm -o preupgradecheck
This is a benign operation, meaning it makes no changes to your farm at all. It simply runs through a list of known issues that occur when upgrading from SharePoint 2007 to SharePoint 2010 and validates your farm. You can see in the command window output that we have one error, colored red.
After the tool is run, it generates a .HTM file that describes the errors it encountered and provides more information on each potential issue.
Right there at the top, we see that our missing feature has caused a potential blocking issue for upgrade.
What About SharePoint 2010?
Oh, astute reader! You are thinking about the upgrade process and wondering if this has been “fixed” in SharePoint 2010. The first thing to address is that there’s really nothing to fix, as this isn’t a bug, it’s working just as it was intended to. The proper sequence is to deactivate and uninstall the feature, as shown in the section above “Cleaning It Up the Right Way”. This behavior did not change for stsadm commands in SharePoint 2010, they remain unchanged so that administrators can continue managing their farms without completely changing all of their scripts.
But wait, SharePoint 2010 has all these great PowerShell cmdlets! Yes, that’s true, there are a ton of new PowerShell cmdlets that give you even greater flexibility for managing SharePoint. But the simple design fact remains that you still have to explicitly deactivate the feature at the specified scope using the cmdlet Disable-SPFeature. Once the feature has been deactivated at the given scope, you can use the new PowerShell cmdlet “Remove-SPSolution” that collapses the minimum of 3 separate stsadm commands into 1 single PowerShell cmdlet that removes the solution from the solution store.