6/26/2012

SharePoint: Search and Replace in Content Editor Web Parts

 

If you are interested in the use of these types of PowerShell scripts to explore and audit SharePoint then you may want to attend my “Exploring and Auditing SharePoint Using PowerShell” session at SharePoint Saturday Dayton this Saturday.

 

 

There’s a question in the MSDN SharePoint forums about how to update Content Editor Web Parts in hundreds of web part pages. These web parts had URLs that pointed to a server that had been renamed, and to fix the URLs meant updating all of these Content Editor Web Parts.

I had recently written a little script to find all of the Content Editor Web Parts in a farm that had a certain piece of text. It only took a small edit to add some code to find and replace text. I have posted the script here instead of the forums as I plan to return here to clean up the code a bit and add more comments.

 

As this script will change, and possibly break, your Content Editor Web Parts… what's below is provided with no warranties and is up to you to test to confirm that it is safe!

 

Steps:

  1. Paste the following into a NotePad file and save as CEWPsearchandreplace.ps1 (or any name you like)
     
  2. Edit these two lines with your before and after text:
        $textToFind = "theBeforeText"
        $newText    = "theAfterText"
     
  3. Start the SharePoint 2010 Management Shell and type: 
          . c:\whereyousavedit\CEWPsearchandreplace.ps1
    Note the dot and the space before the C:

Note that you will need appropriate PowerShell and SharePoint permissions to run this script. See here for more info on permissions: http://techtrainingnotes.blogspot.com/2011/08/searching-and-auditing-sharepoint-with.html

 

Code Notes:

  • The code creates three functions:
    Get-SPWebPartsForWeb  yourURL                (for a single site)"
    Get-SPWebPartsForSite  yourURL                 (for all sites in a site collection)"
    Get-SPWebPartsForApplication  yourURL    (for all site collections in an app)"
     
  • The code only checks for web part pages in selected libraries: "Site Pages","SitePages","Pages"
    You can edit the $librariesToCheck variable to add more locations
     
  • The code also checks the default.aspx page in the site root if $checkrootdefaultaspx = $true
     
  • There are a number of commented out “Write-Host” lines that you can uncomment for debugging purposes.

The code:

"Find and Update Content Editor Web Parts loaded..." 

"Run using:"
"  Get-SPWebPartsForWeb  yourURL         (for a single site)"
"  Get-SPWebPartsForSite  yourURL        (for all sites in a site collection)"
"  Get-SPWebPartsForApplication  yourURL (for all site collections in an app)" 

#  Change these two variables
$textToFind = "theBeforeText"
$newText    = "theAfterText" 

$librariesToCheck = "Site Pages","SitePages","Pages"
$checkrootdefaultaspx = $true 

function Check-Page($page)
{
        # borrow a .NET method GetExtension
        if ([system.io.path]::GetExtension($page.url).ToLower() -ne ".aspx")
        {
          continue #not a webpart page, so back to the foreach
        } 

        # try and get the WebPartManager for the page
        $wpm = $null
        try
        {
          $wpm = $page.GetLimitedWebPartManager([System.Web.UI.WebControls.Webparts.PersonalizationScope]::Shared)
        #"    Webparts: " + $wpm.webparts.count
        }
        catch
        {
          #"   Not a web part page"
        } 

        if ($wpm -ne $null)  # then we have a webpart page
        {
          Write-Host "    Page: " $page.Url 

          # report each web part found
          foreach ($webpart in $wpm.webparts)
          { 

            Write-Host "      Web part: " $webpart.WebBrowsableObject.ToString().Replace("Microsoft.SharePoint.","") -foregroundcolor blue
            Write-Host "         Title: " $webpart.Title
            if ( $webpart.WebBrowsableObject.ToString() -eq "Microsoft.SharePoint.WebPartPages.ContentEditorWebPart" )
            { 

              # if there's linked content then open and search for the script tag
              if  ($webpart.contentlink.length -gt 0 )
              {
                $file = $w.GetFile($webpart.contentlink)
                $b = $file.OpenBinary()
                $encoding=new-object "System.Text.UTF7Encoding"
                if ($encoding.GetString($b).toLower() -match "<script")
                {
                  Write-Host "         contentlink: HAS <SCRIPT>" $webpart.contentlink -foregroundcolor red
                }
                Remove-Variable b
              } 

              # else report what's in the content
              elseif ($webpart.content."#cdata-section".tolower() -match "<script")
                {
                  Write-Host "         content: HAS <SCRIPT>"  -foregroundcolor red 

# write-host $webpart.content."#cdata-section" -foregroundcolor green 

$xmlDoc = New-Object -TypeName xml
$xmlElement = $xmlDoc.CreateElement("MyElement"); 

# THIS IS WHERE THE REPLACE IS DONE.
$xmlElement.InnerText = $webpart.Content.InnerText.Replace($textToFind, $newText); 

$webpart.content = $xmlElement 

$wpm.savechanges($webpart) 

                }
            } 

          }
        } 

} 

filter Get-WebPartPages
{
  # this filter accepts a SPWeb and returns SPPages from target libraries 

# write-host "getting webparts"
  $w = $_
  #Write-Host ""
  #Write-Host "Web: "  $w.ServerRelativeUrl #-foregroundcolor yellow 

  if ($checkrootdefaultaspx)
  {
    #Write-Host "  Root: default.aspx"
    foreach ($file in $w.files)
    {
      if ($file.url -eq "default.aspx")
      {
        $file
      } 
    }
  }
  # Write-Host "now for lists..................." $w.lists.count
  foreach ($list in $w.Lists)
  {
      #Write-Host "  List: " $list.title $librariesToCheck $("'" + $list.title + "'")
    if ( $librariesToCheck -like "*'$($list.title)'*" )
    {
      #Write-Host "File name " -ForegroundColor red
      foreach ($item in $list.items)
      {
        #Write-Host "File name " $item.file.url -ForegroundColor red
        $page = $item.file 

        $page
      }
    }
  }
} 

function Check-WebParts($w)
{ 

  Write-Host ""
  Write-Host "Web: "  $w.ServerRelativeUrl -foregroundcolor yellow 

  if ($checkrootdefaultaspx)
  {
    Write-Host "  Root: "
    foreach ($file in $w.files)
    {
      if ($file.url -eq "default.aspx")
      {
        Check-Page($file)
      } 
    }
  } 

  foreach ($list in $w.Lists)
  {
  Write-Host ("'" + $list.title + "'")
    if ( $librariesToCheck -contains $list.title )
    {
      write-host $list.title
      foreach ($item in $list.items)
      {
        $page = $item.file 

        Check-Page($page)
      }
    }
  } 

} 

Function Get-SPWebPartsForWeb($url)
{
  $web = Get-SPWeb($url)
  Check-WebParts($web)
  $web.Dispose()
} 

Function Get-SPWebPartsForSite($url)
{
  $site = Get-SPSite($url)
  foreach($web in $site.AllWebs)
  {
    Check-WebParts($web)
    $web.Dispose()
  }
  $site.Dispose()
} 

Function Get-SPWebPartsForApplication($url)
{
  $app = Get-SPWebApplication($url)
  foreach ($site in $app.sites)
  {
    foreach($web in $site.AllWebs)
    {
      Check-WebParts($web)
      $web.Dispose()
    }
    $site.Dispose()
  }
}

 

.

6/25/2012

SharePoint Saturday Dayton 2012 this Saturday!

 

It's less than a week to the very first SharePoint Saturday Dayton event. Twenty sessions and twenty speakers means that there's something for everyone… admins, devs, site owners, business owners, and end users. Oh, and don't forget SharePoint Saturday Louisville and SharePoint Saturday Cincinnati coming up in July and October.

It's almost full! Register now or be sorry!

spsdaytonbadge

My Topic: Exploring and Auditing SharePoint Using PowerShell

This session shows how to use PowerShell in both SharePoint 2007 and 2010 to find and extract all kinds of information not easily found using built-in features.  In this session you will see how to use PowerShell to:

• Find all documents in any site, or the entire farm, that matches a pattern (example: *.avi)
• Find all users who have access to a particular file (or folder, or library or site)
• Find sites with no recent activity
• Find all content a single user has access to
• Find all libraries that use a selected Content Type
• Find all customized (un-ghosted) pages
• Find all pages that use a selected web part
• How to collect the results into reports
• and more…

SharePointSaturdaySmall

Reasons to attend SharePoint Saturday Dayton:

  • It's free
  • It's educational
  • You can visit with (and thank) the sponsors
  • It's free
  • There's sessions for everyone
  • You can hobnob with the experts (and maybe get some free consulting)
  • There's door prizes
  • It's air-conditioned
  • It's near by
  • I'm speaking there! (ok, there are better reasons to attend…)
  • Did I mention it's free?

Sessions, speakers, directions and registration can be found here:
http://www.sharepointsaturday.org/dayton/default.aspx

Stay up with SPS Dayton news by following: @spsdayton

Speakers and Sessions:

Visit the site for full session descriptions

6/22/2012

SharePoint Saturday Dayton 2012 in One Week!

 

It's less than a week to the very first SharePoint Saturday Dayton event. Twenty sessions and twenty speakers means that there's something for everyone… admins, devs, site owners, business owners, and end users. Oh, and don't forget SharePoint Saturday Louisville and SharePoint Saturday Cincinnati coming up in July and October.

It's almost full! Register now or be sorry!

Reasons to attend SharePoint Saturday Dayton:

  • It's free
  • It's educational
  • You can visit with (and thank) the sponsors
  • It's free
  • There's sessions for everyone
  • You can hobnob with the experts (and maybe get some free consulting)
  • There's door prizes
  • It's air-conditioned
  • It's near by
  • I'm speaking there! (ok, there are better reasons to attend…)
  • Did I mention it's free?

Sessions, speakers, directions and registration can be found here:
http://www.sharepointsaturday.org/dayton/default.aspx

Stay up with SPS Dayton news by following: @spsdayton

Speakers and Sessions:

Visit the site for full session descriptions

.

6/21/2012

SharePoint: Hide a web part for selected users

 

"Out of the box" there are no "deny permission" features in SharePoint, only grant permissions. If you have a group called Sales with 1000 users, and you would like to use the SharePoint Audience feature to display a web part for everyone in Sales except for Sam, Susan and Bob, you will have to create a new group with 997 users named "Sales except for Sam, Susan and Bob" (and then maintain two groups going forward. But there is a way…

Here's a trick that starts by using a Content Editor Web Part to hide another web part from everyone. By creating a group with our three problem people and using that as an Audience for this CEWP we can selectively hide another web part. 

Before we start, Audiences are not available in WSS 3.0 (2007) or SharePoint 2010 Foundation.

For this trick you need to do four things:

  • Create the group or audience of people to hide things from
  • Discover the ID of the web part you want to hide (see here for 2007 and 2010)
  • Write a bit of CSS to hide the web part
  • Add a Content Editor Web Part to hold or link to the CSS and audience filter it

 

Create the audience:

Your audience can be any AD group (Distribution/Security Group), any SharePoint group you create or a custom audience (Global Audiences) created by your server administrator. For testing proposes you make want to create a test SharePoint group named "TheNoSeeGroup".

The CSS:

The CSS is quite simple, just a "display:none" to hide the entire web part. As this will placed in a Content Editor Web Part that will only be seen by the "TheNoSeeGroup" this CSS will only be effective for those users. The trick here is to get the ID of the web part you want to hide.

    image

Discovering the ID of the web part to hide:

Go to the page with the web part to hide (such as Shared Documents) and use your browser's View Source option to see the page's HTML. Do a search for MSOZoneCell_WebPart and browse around to see if there's any hints that your found the right web part. If not, search again. For more help, go her for 2007 and here 2010. The ID will look something like MSOZoneCell_WebPart9. Note that if you delete and re-add the web part it may receive a new number.

 

Steps:

  1. Find your web part's ID  (MSOZoneCell_WebPart1, MSOZoneCell_WebPart2, etc)
  2. Open Notepad and add the CSS from above using your web part's ID
  3. Save the Notepad file and upload to a SharePoint library in your site (I used Site Assets and named the file HideWebPart.htm)
  4. Go to the library where you loaded the file, right-click the file and select Copy Shortcut (or better, right-click the file, click Properties and copy the URL from there)
  5. Go to the page with the web part you want to hide, edit the page and add a Content Editor Web Part (CEWP) above the web part you want to hide
        image
  6. Edit the CEWP and paste the URL copied earlier for the CSS Notepad file
        image
  7. Click OK… The Shared Documents web part should now be hidden (from everyone!)
  8. Edit the Content Editor Web Part again
  9. In the web part's properties panel expand the Advanced section, scroll to the bottom and select the audience to hide the web part from
        image
    Note that in 2010 the text box has no visible border!
          image
  10. Save your changes and test by have a group member, and a non-group member, log in and see if the web part is displayed.

Note for 2010: If you can't see the CEWP when you edit the page (to edit it or to delete it) it's because you are not in the right group! Either add yourself to the "hide from" group or use a trick from here to display a list of all of the web parts, append ?Contents=1 or &Contents=1 to the end of the page's URL.

.

Note to spammers!

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.