You have to delete those deployed files yourself in the FeatureDeactivating event. The classic approach is to delete the files one-by-one, but this is tedious and error-prone. The following is a set of extension methods that allows you to simply do this:
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPSite site = (SPSite) properties.Feature.Parent;
properties.Definition.DeleteFeatureFiles("MasterPages", site.RootWeb);
properties.Definition.DeleteFeatureWebPartFiles(site.RootWeb);
}
The code is an adaptation of Corey Roth's LINQ to XML and Deleting Files on Feature Deactivation, using extension methods and supporting cleanup of specific feature modules and all feature web-parts.
namespace Puzzlepart.SharePoint.Core.SPExtentions
{
public static class SPFeatureDefinitionExtentions
{
public class Module
{
public string Name { get; set; }
public string Path { get; set; }
public List<string> Files { get; set; }
}
public static void DeleteFeatureFiles
(this SPFeatureDefinition spFeatureDefinition, string moduleName, SPWeb web)
{
List<Module> modules = GetModuleFiles(spFeatureDefinition, moduleName);
foreach (Module module in modules)
{
DeleteModuleFiles(module, web);
}
}
public static void DeleteFeatureWebPartFiles
(this SPFeatureDefinition spFeatureDefinition, SPWeb web)
{
List<Module> modules = GetAllModuleFiles(spFeatureDefinition);
foreach (Module module in modules)
{
if (string.Compare(module.Path, "_catalogs/wp",
StringComparison.CurrentCultureIgnoreCase) == 0)
DeleteModuleFiles(module, web);
}
}
private static List<Module> GetModuleFiles
(SPFeatureDefinition spFeatureDefinition, string moduleName)
{
string elementsPath = string.Format(@"{0}\FEATURES\{1}\{2}\Elements.xml",
SPUtility.GetGenericSetupPath("Template"),
spFeatureDefinition.DisplayName, moduleName);
XDocument elementsXml = XDocument.Load(elementsPath);
XNamespace sharePointNamespace = "http://schemas.microsoft.com/sharepoint/";
// get each module name and the files in it
var moduleList =
from module in elementsXml.Root.Elements(sharePointNamespace + "Module")
select new
{
Name = (module.Attributes("Name").Any())
? module.Attribute("Name").Value : null,
ModuleUrl = (module.Attributes("Url").Any())
? module.Attribute("Url").Value : null,
Files = module.Elements(sharePointNamespace + "File")
};
List<Module> modules = new List<Module>();
// iterate through each module with files
foreach (var module in moduleList)
{
Module m = new Module()
{
Name = module.Name,
Path = module.ModuleUrl
};
List<string> files = new List<string>();
foreach (var fileElement in module.Files)
{
string filename = (fileElement.Attributes("Name").Any())
? fileElement.Attribute("Name").Value : fileElement.Attribute("Url").Value;
files.Add(filename);
}
m.Files = files;
modules.Add(m);
}
return modules;
}
private static void DeleteModuleFiles(Module module, SPWeb web)
{
foreach (string filename in module.Files)
{
if (!string.IsNullOrEmpty(module.Path))
web.GetFile(string.Format("{0}/{1}", module.Path, filename)).Delete();
else
web.Files.Delete(filename);
}
}
private static List<Module> GetAllModuleFiles
(SPFeatureDefinition spFeatureDefinition)
{
var moduleList = new List<Module>();
string modulesPath = string.Format(@"{0}\FEATURES\{1}\",
SPUtility.GetGenericSetupPath("Template"),
spFeatureDefinition.DisplayName);
DirectoryInfo folder = new DirectoryInfo(modulesPath);
foreach (DirectoryInfo moduleFolder in folder.GetDirectories())
{
moduleList.AddRange(GetModuleFiles(spFeatureDefinition, moduleFolder.Name));
}
return moduleList;
}
}
}
Note that page layouts cannot simply be deleted if they are in use. Use code to revert the "GhostableInLibrary" files to the uncustomized (ghosted) feature files on disk in the SharePoint root [14].
1 comment:
Thank you so much for script as we had been search engine it. But finally your blog has helped us.
Post a Comment