Updating the docicon.xml File with a Feature


File types are associated to an icon in SharePoint by mapping a particular file extension to a specific icon. This makes the file easily recognizable to end users as they navigate a site and skim a document library. For licensing reasons, only a select list of file types has an icon associated with them by default. This also helps prevent bloating the document icon list with an exhaustive list of file types.


You can map a file extension to a particular icon in SharePoint by editing the docicon.xml file and adding a mapping element with the file extension and icon path. This file is located in the TEMPLATES\XML folder within the SharePoint 12 hive. You will need to edit this file on each web front-end server, making it a good candidate to accidently have a server go out of sync with the other servers. No different from challenges faced with any manual configuration or customization. By instead making the changes via a SharePoint feature, the solution is repeatable, testable, and ensures all servers reflect any changes.


To illustrate an example I will use a file type I often like to add an icon for, PDF files. I created a new feature with a farm scope and a receiver class to override the FeatureActivated and FeatureDeactivating methods. Below is my code for the FeatureActivated method where it loads the docicon.xml document, check if a mapping element exists for the PDF extension, and add one if not.


Being fussy about my code and maintaining consistency, I first attempt to add the new PDF Mapping element in alphabetical order by checking for a file extension in the list that would fall after "PDF" and insert the node before that. Otherwise, I append the PDF Mapping element as the last element. Finally, I save the file overwriting the original with the changes.


public override void FeatureActivated(SPFeatureReceiverProperties properties)


{


    XmlDocument xmlDocument = new XmlDocument();


    xmlDocument.Load(DocIconFilePath);


    XmlNode documentElement = xmlDocument.DocumentElement;


    XmlNode pdfNode = documentElement.SelectSingleNode("ByExtension/Mapping[@Key='pdf']");


    if (pdfNode == null)


    {


        pdfNode = xmlDocument.CreateElement("Mapping");


        pdfNode.Attributes.Append(


        xmlDocument.CreateAttribute("Key")).Value = "pdf";


        pdfNode.Attributes.Append(


        xmlDocument.CreateAttribute("Value")).Value = "pdf.gif";


        bool wasAdded = false;


        XmlNode byExtensionNode = documentElement.SelectSingleNode("ByExtension");


        foreach (XmlNode node in byExtensionNode.ChildNodes)


        {


            if (node.Attributes["Key"].Value.CompareTo("pdf") > 0)


            {


                byExtensionNode.InsertBefore(pdfNode, node);


                wasAdded = true;


                break;


            }


        }


        if (!wasAdded)


            byExtensionNode.AppendChild(pdfNode);


        xmlDocument.Save(DocIconFilePath);


    }


}


The FeatureDeactivating method reverses the configuration changes when administrators deactivate the feature. However, changes may require recycling an application pool before the changes take effect and the icon reverts to the common plain white one. Below is my code for the FeatureDeactivating method where it loads the same docicon.xml file and checks if a Mapping element exists for the PDF extension. If a PDF Mapping element exists, it removes the element and then saves the file back with the changes.


public override void FeatureDeactivating(SPFeatureReceiverProperties properties)


{


    XmlDocument xmlDocument = new XmlDocument();


    xmlDocument.Load(DocIconFilePath);


    XmlNode documentElement = xmlDocument.DocumentElement;


    XmlNode pdfNode = documentElement.SelectSingleNode("ByExtension/Mapping[@Key='pdf']");


    if (pdfNode != null)


    {


        XmlNode byExtensionNode = documentElement.SelectSingleNode("ByExtension");


        byExtensionNode.RemoveChild(pdfNode);


        xmlDocument.Save(DocIconFilePath);


    }


}


Loading and saving the docicon.xml file in the FeatureActivated and FeatureDeactivating methods use the DocIconFilePath property. This property looks up and builds the path on first access. Below is my code for the property where I combine the TEMPLATE\XML directory with the docicon.xml file to build the full path.


Instead of hard coding the directory to the most common path of the 12 hive, I used a static utility method in the SharePoint API to encapsulate the path and make it less fragile to changes. Calling SPUtility.GetGenericSetupPath with an empty string will return the full path to the 12 hive as a string (most typically this path is "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12"). The utility takes string parameters and combines them as a subdirectory of the 12 hive, and then returns the full path with the subdirectory.


private string _docIconFilePath;


private string DocIconFilePath


{


    get


    {


        if (_docIconFilePath == null)


            _docIconFilePath = Path.Combine(


                SPUtility.GetGenericSetupPath("TEMPLATE\\XML"),


                "DOCICON.XML");


        return _docIconFilePath;


    }


}


I deploy the PDF icon file in the WSP solution package with the feature by adding a command to the DDF file that copies it to an Images directory in the WSP. The solution manifest file includes the following TemplateFile element that copies the PDF icon file to the TEMPLATE\IMAGES directory of the 12 hive for each server in the farm during solution deployment.


<TemplateFiles>


    <TemplateFile Location="IMAGES\pdf.gif" />


Once the solution is packaged and deployed on the server, activate the feature in the farm features management area of SharePoint Central Administration. Upload a PDF file to a document library and verify the icon next to it matches the icon set in this feature.

Comments (7)

  1. Yeshwanth says:

    Hi Steve,

    Will this work for all the servers on the farm or does it works on only the server where you deploy the feature?

    -Yesh

  2. joshgavant says:

    Steve,

    This seems to only effect one server randomly. Probably could write some code to have it cycle through the servers. Thanks for the ideas in any case.

    ~Josh

  3. Lars Nielsen says:

    Thanks Steve this is a great idea and very useful code for updating XML files.  In the future if the DOCICON.XML file is overwritten by a service pack or update, you just de-activate the feature before applying the patch and activate again afterwards.  You could use this code as a basis to wrap up all the SharePoint customisations into a feature that can be de-activated and re-activated after each patch.  

    The SDK has a good article on this here:

    http://msdn.microsoft.com/en-us/library/aa978104.aspx

    Note that if you use a special icon GIF with an anonymous access site, you need make sure that the permissions on the GIF file are set to inherit from the parent.  Presumably that happens anyway if the GIF is deployed as part of a solution - so if you wrapped this feature into a solution along with the required GIF icons, it would work well.

    Yesh, in answer to your question, you don't deploy a feature to a particular server, you deploy it across the farm so it will work on all the servers.

  4. sgoodye says:

    Try moving the logic from the FeatureActivated to the FeatureInstalled event instead. I believe this executes on each server.

Skip to main content