MOSS Recursive Search and Replace

23 Aug

Ever find yourself needing to make an edit across every page and every site in your SharePoint 2007 portal? It does seem a bit of a brutal operation, but it has saved me many times doing everything from fixing navigation links to fixing upgrade errors.

I’ve put together a bit of code to recursively iterate through all the site collections and pages in your farm (or below the specified URL), check out the page, do a replace in the page source, and check it back in. This is a heck of a lot faster than sitting in front of SharePoint Designer for days at a time!

The actual find and replace is done something like this. Keep in mind we’ve anticipated the publishing features are enabled, if your not using them you’ll likely have to make some tweaks.

<p><span class="kwrd">if</span> (myItem.Properties[<span class="str">"PublishingPageLayout"</span>].ToString().Contains(Find))<br />{<br />   PublishingPage myPage = PublishingPage.GetPublishingPage(myItem);<br />   myPage.CheckOut();<br />   myItem.Properties[<span class="str">"PublishingPageLayout"</span>] = myItem.Properties  [<span class="str">"PublishingPageLayout"</span>].ToString().Replace(Find, Replace);<br />   myItem.Update();<br />   myPage.CheckIn(<span class="kwrd">string</span>.Empty);<br />   myPage.ListItem.File.Publish(<span class="kwrd">string</span>.Empty);<br />   <span class="kwrd">if</span> (myPage.ListItem.ParentList.EnableModeration)<br />   {<br />       myPage.ListItem.File.Approve(<span class="kwrd">string</span>.Empty);<br />   }<br />                     <br />}</p>

The constructor for the class looks like this, and takes 4 parameters:

<span class="kwrd">public</span> <span class="kwrd">void</span> FindReplace(<span class="kwrd">string</span> BaseURL, <span class="kwrd">string</span> Find, <span class="kwrd">string</span> Replace, <span style="color:#0000ff;">string</span> WebApp)<br />{<br />   SPWebService myWebService = SPWebService.ContentService;<br />   SPWebApplication myWebApp = myWebService.WebApplications[WebApp];<br />   SPSite mySite = myWebApp.Sites[BaseURL];<br />   SPWeb myWeb = mySite.OpenWeb();<br /><br />   FixRecursive(myWeb, Find, Replace, <span class="str">"Pages"</span>);<br />   Fix(myWeb, Find, Replace, <span class="str">"Pages"</span>);<br />}

BaseURL is the root node at which we will start the replace. Anything below this will be processed. WebApp is the actual string name of the web application in IIS. This was the best way I could find to handle load-balanced farms. For example “SharePoint – 80”, etc. You can modify this to get your Web object however you like.

And here is the full class I’m using, hopefully it will get you headed towards your own solution. I’m hesitant to provide an executable or full project, as someone is likely to really fry their installation 😉

<span class="kwrd">public</span> <span class="kwrd">class</span> FindReplace
{
 
    <span class="kwrd">public</span> FindReplace(<span class="kwrd">string</span> BaseURL, <span class="kwrd">string</span> Find, <span class="kwrd">string</span> Replace, <span class="kwrd">string</span> WebApp)
    {
        SPWebService myWebService = SPWebService.ContentService;
        SPWebApplication myWebApp = myWebService.WebApplications[WebApp];
        SPSite mySite = myWebApp.Sites[BaseURL];
        SPWeb myWeb = mySite.OpenWeb();
 
        FixRecursive(myWeb, Find, Replace, <span class="str">"Pages"</span>);
        Fix(myWeb, Find, Replace, <span class="str">"Pages"</span>);
    }
 
    <span class="kwrd">private</span> <span class="kwrd">void</span> FixRecursive(SPWeb myWeb, <span class="kwrd">string</span> Find, <span class="kwrd">string</span> Replace, <span class="kwrd">string</span> ListTitle)
    {
        <span class="kwrd">foreach</span> (SPWeb web <span class="kwrd">in</span> myWeb.Webs)
        {
            FixRecursive(web, Find, Replace, ListTitle);
            Fix(web, Find, Replace, ListTitle);
        }
    }
 
    <span class="kwrd">public</span> <span class="kwrd">bool</span> Fix(SPWeb myWeb, String Find, String Replace, String ListTitle)
    {
        <span class="kwrd">try</span>
        {
            Console.WriteLine(myWeb.Url);
            SPListItemCollection myItems = myWeb.Lists[ListTitle].Items;
            <span class="kwrd">foreach</span> (SPListItem myItem <span class="kwrd">in</span> myItems)
            {
                <span class="kwrd">if</span> (myItem.Properties[<span class="str">"PublishingPageLayout"</span>].ToString().Contains(Find))
                {
                    Console.WriteLine(<span class="str">"   -&gt; "</span> + myItem.Title);
                    PublishingPage myPage = PublishingPage.GetPublishingPage(myItem);
                    myPage.CheckOut();
                    myItem.Properties[<span class="str">"PublishingPageLayout"</span>] = myItem.Properties[<span class="str">"PublishingPageLayout"</span>].ToString().Replace(Find, Replace);
                    myItem.Update();
                    myPage.CheckIn(<span class="kwrd">string</span>.Empty);
                    myPage.ListItem.File.Publish(<span class="kwrd">string</span>.Empty);
                    <span class="kwrd">if</span> (myPage.ListItem.ParentList.EnableModeration)
                    {
                        myPage.ListItem.File.Approve(<span class="kwrd">string</span>.Empty);
                    }
                    Console.WriteLine(<span class="str">"Done."</span>);
                }
            }
        }
        <span class="kwrd">catch</span> (Exception ex)
        {
            Console.WriteLine(<span class="str">"ERROR: "</span> + ex.Message);
            <span class="kwrd">return</span> <span class="kwrd">false</span>;
        }
        <span class="kwrd">return</span> <span class="kwrd">true</span>;
    }  
}

Tweet about this on TwitterShare on Google+Share on FacebookShare on RedditEmail this to someoneShare on LinkedInShare on StumbleUpon

Leave a Reply

Your email address will not be published. Required fields are marked *