Skip to content

The Chris Kent

Quick Fixes, Workarounds, and Other Neat Tricks

  • Home
  • About
  • Speaking
HomePosts tagged 'User Control'

User Control

Changing a UserControl in the 14 Hive Using a Custom Timer Job

May 10, 2012May 9, 2012 theChrisKent .NET, List/Library Settings, MetaDataNavExpansion, SharePoint Managed Metadata, MetaData Navigation, MetaDataNavExpansion, MetaDataNavTree, SharePoint, SPServiceJobDefinition, Timer Job, User Control, WireBear
Applies To: SharePoint 2010, .NET Framework (C#, VB.NET)

As mentioned in a previous post, I’ve recently put together a solution for automatically updating the MetaDataNavTree.ascx User Control to default the MetaData Navigation expansion to include the actual taxonomy items. You can download the solution as well as the source for free from CodePlex here: WireBear MetaDataNavExpansion.

This post is very similar to my post Updating an XML File in the 14 Hive Using a Custom Timer Job and assumes you know some basics about custom timer job creation (If not, check my other post Implementing a Custom SharePoint Timer Job). Either way, most of the code will be given right here anyway.

The goal for this timer job is to either backup the MetaDataNavTree.ascx file in the 14\TEMPLATE\CONTROLTEMPLATES folder with the SharePoint Hive and to adjust the Tree’s ExpandDepth property from 0 to 2 or to restore the backup previously made. Here is the entire MetaDataNavExpansionJob class:

Imports Microsoft.SharePoint.Administration
Imports Microsoft.SharePoint.Utilities
Imports System.Text.RegularExpressions

Public Class MetaDataNavExpansionJob
    Inherits SPServiceJobDefinition

#Region "Properties"

    Private _userControlPath As String
    Public ReadOnly Property UserControlPath() As String
        Get
            If String.IsNullOrEmpty(_userControlPath) Then _userControlPath = SPUtility.GetGenericSetupPath("TEMPLATE\CONTROLTEMPLATES\MetadataNavTree.ascx")
            Return _userControlPath
        End Get
    End Property

    Private _userControlBackupPath As String
    Public ReadOnly Property UserControlBackupPath() As String
        Get
            If String.IsNullOrEmpty(_userControlBackupPath) Then _userControlBackupPath = SPUtility.GetGenericSetupPath("TEMPLATE\CONTROLTEMPLATES\MetadataNavTree.ascx.bak")
            Return _userControlBackupPath
        End Get
    End Property

    Private Const InstallingKey As String = "DocIconJob_InstallingKey"
    Private Property _installing() As Boolean
        Get
            If Properties.ContainsKey(InstallingKey) Then
                Return Convert.ToBoolean(Properties(InstallingKey))
            Else
                Return True
            End If
        End Get
        Set(ByVal value As Boolean)
            If Properties.ContainsKey(InstallingKey) Then
                Properties(InstallingKey) = value.ToString
            Else
                Properties.Add(InstallingKey, value.ToString)
            End If
        End Set
    End Property

#End Region

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(JobName As String, service As SPService, Installing As Boolean)
        MyBase.New(JobName, service)
        _installing = Installing
    End Sub

    Public Overrides Sub Execute(jobState As Microsoft.SharePoint.Administration.SPJobState)
        AdjustMetaDataNavExpansion()
    End Sub

    Private Sub AdjustMetaDataNavExpansion()
        If _installing Then
            If My.Computer.FileSystem.FileExists(UserControlPath) Then
                'Backup the original
                My.Computer.FileSystem.CopyFile(UserControlPath, UserControlBackupPath, True)
                Dim contents As String = My.Computer.FileSystem.ReadAllText(UserControlPath)

                'Replace the Expansion with First Level Expansion
                My.Computer.FileSystem.WriteAllText(UserControlPath, Regex.Replace(contents, "ExpandDepth=""\d+""", "ExpandDepth=""2"""), False)
            End If
        Else
            If My.Computer.FileSystem.FileExists(UserControlBackupPath) Then
                'Restore the original
                My.Computer.FileSystem.MoveFile(UserControlBackupPath, UserControlPath, True)
            End If
        End If
    End Sub

End Class

Lines 8-44 are just the declaration of and logic needed to persist some properties. Again, more information can be found in my previous post, but basically I am using the SPJobDefinition’s Properties HashTable to store my own properties as specified in the constructor. Except for in the case of the UserControlPath and UserControlBackupPath properties which are really just wrapping up some logic to get a reference to specific files in the 14 Hive’s TEMPLATE\CONTROLTEMPLATES directory using the SPUtility class.

The Execute method beginning in line 55 is what is called when the Timer Job actually runs. I override this method to ensure my custom code gets called instead. My custom code really begins in the AdjustMetaDataNavExpansion method starting at line 59.

If this job is installing (Running on Solution Activation), the MetaDataNavTree.ascx file is copied to MetaDataNavTree.ascx.bak as a backup of the original in line 63. The UserControl file is then read in as text and a regular expression searches for and replaces the ExpandDepth=”SomeNumber” property and replaces it with ExpandDepth=”2″. This is all done and saved back into the file in lines 66-67.

If this job is uninstalling (Running on Solution Deactivation), the backup file (MetaDataNavTree.ascx.bak) created on activation is restored in line 72.

To run this from activation and deactivation I simply copy my design from the PDFdocIcon project and create and run a new version of the job. Since this code is nearly identical to what I’ve already explained, I won’t go into detail but I will save you some time and have copied it below. This is the Main.EventReceiver:

Option Explicit On
Option Strict On

Imports System
Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Security
Imports Microsoft.SharePoint.Administration

''' <summary>
''' This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
''' </summary>
''' <remarks>
''' The GUID attached to this class may be used during packaging and should not be modified.
''' </remarks>

<GuidAttribute("a885d247-f5e8-4456-abd2-6cfebb2bdfde")> _
Public Class MainEventReceiver
    Inherits SPFeatureReceiver

    Public Sub RunMetaDataNavExpansionJob(Installing As Boolean, properties As SPFeatureReceiverProperties)
        Dim JobName As String = "MetaDataNavExpansionJob"

        'Ensure job doesn't already exist (delete if it does)
        Dim query = From job As SPJobDefinition In properties.Definition.Farm.TimerService.JobDefinitions Where job.Name.Equals(JobName) Select job
        Dim myJobDefinition As SPJobDefinition = query.FirstOrDefault()
        If myJobDefinition IsNot Nothing Then myJobDefinition.Delete()

        Dim myJob As New MetaDataNavExpansionJob(JobName, SPFarm.Local.TimerService, Installing)

        'Get that job going!
        myJob.Title = String.Format("Configuring MetaData Navigation for {0} Expansion", IIf(Installing, "First Level", "Default"))
        myJob.Update()
        myJob.RunNow()
    End Sub

    Public Overrides Sub FeatureActivated(ByVal properties As SPFeatureReceiverProperties)
        RunMetaDataNavExpansionJob(True, properties)
    End Sub

    Public Overrides Sub FeatureDeactivating(ByVal properties As SPFeatureReceiverProperties)
        RunMetaDataNavExpansionJob(False, properties)
    End Sub

End Class

I hope you’re beginning to see that automating any manual changes to the 14 Hive can follow the Service Timer Job Solution pattern I’ve now demonstrated twice. This isn’t true for everything (Web.config changes should be done through the object model or a config.something.xml file, workflow actions can have their own file, etc.), but for those little one off things that don’t have a better alternative, this is a great way to take care of it.

Rate this:

Share this:

  • Twitter
  • Facebook
  • More
  • Print
  • Email
  • Tumblr
  • Pinterest
  • Reddit
  • LinkedIn

Like this:

Like Loading...
Leave a comment

Office Development

Recent Posts

  • Convert Modern SharePoint Page Banner Images to Base-64 using PowerShell
  • Missing SharePoint Online Classic Administration Links
  • Extending the List of Sites You can Embed From in SharePoint Using PowerShell
  • Thank you SharePoint Conference!
  • Customizing the Flow Panel with List Formatting actionParams

Popular Posts

  • Applying Column Formats to Multi-line Text Fields
  • Embedded Chromium in WinForms
  • Simple SharePoint FAQ in 5 Minutes
  • Taking Advantage of the Loading Indicator in the SharePoint Framework
  • Showing Icons in a List View

Archives

  • June 2020
  • April 2020
  • November 2019
  • May 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • August 2018
  • July 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • January 2018
  • December 2017
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • July 2017
  • June 2017
  • May 2017
  • April 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • January 2016
  • August 2015
  • April 2015
  • February 2015
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • May 2014
  • April 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • August 2013
  • March 2013
  • February 2013
  • January 2013
  • November 2012
  • October 2012
  • September 2012
  • August 2012
  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
Create a website or blog at WordPress.com
  • LinkedIn
  • Twitter
loading Cancel
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.
%d bloggers like this: