3

I have a bunch (technical term) of publishing pages within a single subsite of my site collection that contain a broken link. I'm wonder if it's at all possible to use Powershell to perform a 'global' update on all these pages?

Something like:

  1. check out page
  2. open page in edit mode
  3. get HTML from a content editor web part (CEWP)
  4. find the broken link and replace with the correct link
  5. update the CEWP
  6. save, check in and publish the page

Is anything like that possible? Alternatively, is there a way to find text in SQL? I'm wondering if I can locate individual pages within SQL and make the changes?

Cheers

Kevin

2
  • 1
    You should never directly modify anything in SharePoint via the SQL database. This is not only not supported but if MS ever finds out that you have done this they will not support your configuration in the future. Commented Apr 12, 2012 at 12:53
  • agreed - clutching at straws, they call it ;)
    – QMKevin
    Commented Apr 12, 2012 at 17:05

2 Answers 2

2

Yupp, that's possible using PowerShell and no, do not edit the content database as you'll bring more trouble than fixes.

I've been doing the same operation but within a straight forward console application. You could convert it to a powershell script. Please find below how I parsed a whole site collection and check for specific webpart, update the webpart if the page is not exclusively checked-out and log the whole operation. This will give you most (if not all) the relevant SharePoint object that should be used.

            int processedItemNoActionCount = 0;
            int processedItemSuccessCount = 0;
            int unProcessedItemsWarningCount = 0;
            int unProcessedItemsErrorCount = 0;

            using (SPSite site = new SPSite(*YourSiteCollectionUrl*))
            {
                foreach(SPWeb web in site.AllWebs)
                {
                    Log.Info("Reviewing " + web.ServerRelativeUrl);
                    using(SPWeb currentWeb = site.OpenWeb(web.ID))
                    {
                        PublishingWeb publishingWeb;
                        try
                        {
                            publishingWeb = PublishingWeb.GetPublishingWeb(currentWeb);
                            PublishingPageCollection publishingPageCollection = publishingWeb.GetPublishingPages();

                            foreach (PublishingPage page in publishingPageCollection)
                            {
                                try
                                {
                                    Console.Write(".");
                                    Log.Info("\tReviewing " + page.Uri);


                                    bool reviewRequired = false;
                                    // check if there is any webpart of type WPBanner, WPCarrousel or WPSimulator - the page must be checkout before using the webpart manager -> only check-it out if really necessary !
                                    using (SPLimitedWebPartManager limitedWebPartManager = page.ListItem.File.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))
                                    {

                                        // analyze if any webpart needs to be updated
                                        for (int i = 0; i < limitedWebPartManager.WebParts.Count; i++)
                                        {
                                            System.Web.UI.WebControls.WebParts.WebPart webPart =
                                                limitedWebPartManager.WebParts[i];

                                            string webPartTypeName = webPart.GetType().Name;
                                            if (string.Equals(ConfigurationManager.AppSettings["WebPartBanner"], webPartTypeName, StringComparison.OrdinalIgnoreCase) || 
                                                string.Equals(ConfigurationManager.AppSettings["WebPartCarousel"], webPartTypeName, StringComparison.OrdinalIgnoreCase) || 
                                                string.Equals(ConfigurationManager.AppSettings["WebPartSimulatorTool"], webPartTypeName, StringComparison.OrdinalIgnoreCase))
                                            {
                                                reviewRequired = true;
                                                break;
                                            }
                                        }
                                    }

                                    if (reviewRequired)
                                    {
                                        if (page.ListItem.File.CheckOutType != SPFile.SPCheckOutType.None)
                                        {
                                            Log.WarnFormat("\t-> Warning - WebPart(s) containing WCC reference(s) found but the page is checked-out. Unable to update the webparts without risking data loss. Please review the page {0} manually.", page.Uri);
                                            unProcessedItemsWarningCount++;
                                        }
                                        else
                                        {
                                            page.ListItem.File.CheckOut();

                                            using (SPLimitedWebPartManager limitedWebPartManager = page.ListItem.File.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))
                                            {
                                                for (int i = 0; i < limitedWebPartManager.WebParts.Count; i++)
                                                {
                                                    System.Web.UI.WebControls.WebParts.WebPart wp = limitedWebPartManager.WebParts[i];

                                                    if (string.Equals(ConfigurationManager.AppSettings["WebPartBanner"], wp.GetType().Name, StringComparison.OrdinalIgnoreCase))
                                                    {
                                                        WPBanner wpBanner = wp as WPBanner;
                                                        if (wpBanner != null)
                                                        {

                                                            bool update = false;
                                                            if (ReferencesDictionary.ContainsKey(wpBanner.BannerToDisplayGuid))
                                                            {
                                                                wpBanner.BannerToDisplayGuid = ReferencesDictionary[wpBanner.BannerToDisplayGuid];
                                                                update = true;
                                                            }
                                                            if (ReferencesDictionary.ContainsKey(wpBanner.FallBackBannerGuid))
                                                            {
                                                                wpBanner.FallBackBannerGuid = ReferencesDictionary[wpBanner.FallBackBannerGuid];
                                                                update = true;
                                                            }

                                                            if (update)
                                                            {
                                                                limitedWebPartManager.SaveChanges(wpBanner);
                                                                Log.InfoFormat("\t-> Update - The Banner WebPart '{0}' has been reviewed and updated.",wpBanner.Title);
                                                            }
                                                        }
                                                    }

                                                    else if (string.Equals(ConfigurationManager.AppSettings["WebPartCarousel"],wp.GetType().Name,StringComparison.OrdinalIgnoreCase))
                                                    {
                                                        WPCarousel wpCarousel = wp as WPCarousel;

                                                        if (wpCarousel != null)
                                                        {
                                                            bool update = false;
                                                            if (
                                                                ReferencesDictionary.ContainsKey(wpCarousel.CarouselToDisplayGuid))
                                                            {
                                                                wpCarousel.CarouselToDisplayGuid = ReferencesDictionary[wpCarousel.CarouselToDisplayGuid];
                                                                update = true;
                                                            }
                                                            if (
                                                                ReferencesDictionary.ContainsKey(wpCarousel.FallBackBannerGuid))
                                                            {
                                                                wpCarousel.FallBackBannerGuid = ReferencesDictionary[wpCarousel.FallBackBannerGuid];
                                                                update = true;
                                                            }

                                                            if (update)
                                                            {
                                                                limitedWebPartManager.SaveChanges(wpCarousel);
                                                                Log.InfoFormat("\t-> Update - The Carousel WebPart '{0}' has been reviewed and updated.",wpCarousel.Title);
                                                            }
                                                        }
                                                    }
                                                    else if (string.Equals(ConfigurationManager.AppSettings["WebPartSimulatorTool"], wp.GetType().Name,StringComparison.OrdinalIgnoreCase))
                                                    {
                                                        WPSimulatorTool wpSimulatorTool = wp as WPSimulatorTool;
                                                        if (wpSimulatorTool != null)
                                                        {
                                                            if (ReferencesDictionary.ContainsKey(new Guid(wpSimulatorTool.SimulatorGuid)))
                                                            {
                                                                wpSimulatorTool.SimulatorGuid = ReferencesDictionary[new Guid(wpSimulatorTool.SimulatorGuid)].ToString();
                                                                limitedWebPartManager.SaveChanges(wpSimulatorTool);
                                                                Log.InfoFormat("\t-> Update - The Simulator WebPart '{0}' has been reviewed and updated.",
                                                                    wpSimulatorTool.Title);
                                                            }
                                                        }
                                                    }
                                                }
                                            }

                                            if (page.ListItem.File.CheckOutType != SPFile.SPCheckOutType.None)
                                            {
                                                page.ListItem.File.CheckIn("System Update - WCC Content WebPart(s) have been updated");
                                                page.ListItem.File.CheckIn("", SPCheckinType.MajorCheckIn);
                                                page.ListItem.File.Publish();
                                                page.ListItem.File.Approve();
                                            }

                                            Log.InfoFormat("\t-> Success - The webpart(s) have been updated and the page has been saved successfully (minor checked-in). A major publish might be required.");
                                            processedItemSuccessCount++;
                                        }
                                    }
                                    else
                                    {
                                        Log.Info("\t-> No Action - No relevant webpart found within the page.");
                                        processedItemNoActionCount++;
                                    }
                                }
                                catch (Exception exception)
                                {
                                    Log.ErrorFormat("Unable to review the page located at {0} due to : {1}.", page != null ? page.Url : " [ url property unavailable - page is null ] ", exception);
                                    unProcessedItemsErrorCount++;
                                }
                            }
                        }
                        catch (Exception exception)
                        {
                            Log.ErrorFormat("Unable to review the web located at {0} due to : {1}.", web.ServerRelativeUrl, exception);
                        }
                    }
                }

                OutputMessage("-> Pages reviewed and successfully updated : " + processedItemSuccessCount);
                OutputMessage("-> Pages reviewed but not modified (no action needed) : " + processedItemNoActionCount);
                OutputMessage("-> Pages requiring a manual review (checked-out, deprecated references,...) : " + unProcessedItemsWarningCount);
                OutputMessage("-> Unprocessed pages due to error(s) : " + unProcessedItemsErrorCount);
4
  • A C# solution works just as well for me! Many thanks Francois. It may take some time for me to decipher the entire method and apply it to my environment, but this is just the first step I need. Thank you very much :)
    – QMKevin
    Commented Apr 12, 2012 at 22:40
  • Glad to read that I was able to help :) Commented Apr 13, 2012 at 7:20
  • Just wanted to say thanks again. With a lot of help from your script, and some from another article, which I found based on knowledge gained from understanding your script, I was able to create my own script to update my site, and it works :)
    – QMKevin
    Commented Apr 20, 2012 at 12:26
  • Thanks a lot for the update. I'm delighted to see it managed to solved more than one customer issue :) Commented Apr 20, 2012 at 13:30
2

This is a really interesting question and I would really enjoy writing up a script for you but this would take me a pretty long time. So I will have to stick to giving you some general advice on how to do it.

Using PowerShell

  1. List item
  2. Check out the page.
  3. Download the page to the local FS.
  4. Using Get-Content or similar scrape the page for URLs inside the CEWP.
  5. Once you match the URLs you can use WebRequest to verify that the URLs exist.
  6. If not replace them with your values.
  7. Write back to the ASPX page.
  8. Upload the file back to SharePoint using WebClient and PUT.
  9. Check the item back in.

If I were doing this I might actually use Python for scraping and verifying the URLs as I think it is a little easier to work with strings and such.

WebRequest

$url = "http://companyweb"
$request=[system.Net.HttpWebRequest]::Create($url);
$response = $request.getresponse();
$status = $response.statuscode;
$response.Close();

WebClient - I've not tested this, just giving you an example from memory...

$userName = "userName";
$password = "OhSoSectret!";
$domain = "doamin";
$remoteFileURL = "https://companyweb/teams/it/Shared Documents/" + $fileName;
$filePath = "C:\path\file.aspx"

$webclient = New-Object System.Net.WebClient
$webclient.Credentials = [System.Net.NetworkCredential]::($userName, $password, $domain);
$webclient.UploadFile($remoteFileURL, "PUT", $filePath);
$webclient.Dispose();
1
  • Many thanks for your solution, Robert. I'm going to look at this as well as Francois's solution, though the C# method is much more comfortable for me to work with - I'm still relatively new to Powershell.
    – QMKevin
    Commented Apr 12, 2012 at 22:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.