none
Applying theme to all sites in a site collection SharePoint Foundation 2010 RRS feed

  • Question

  • I am working in SharePoint Foundation 2010 and want to apply a theme found in my top level site to all the remaining sites in the site collection.  I found the following bit of code on-line and put it in a script:

    function Apply-SPTheme([string]$SiteUrl, [string]$webName, [string]$themeName)
    {
     $site = new-object Microsoft.SharePoint.SPSite($SiteUrl)
     $web = $Site.OpenWeb($webName)
     $theme = [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catatlogs/theme/" + $themeName + ".thmx")
     $theme.ApplyTo($web,$false)
     $web.Update()
     $web.Dispose()
     $site.Dispose()
    }
    Apply-SPTheme "https://sitename" "" "themeName"

    I call the function in the last line and the web site where I obtained the code indicated that this would put the theme in all other sites.  When I run the script I get the follwing message:

    You cannot call a method on a null-valued expression. At C:\applyTheme.ps1(the script file):6 char:16

    $theme.ApplyTo <<<< <$web,$false>

    +CategoryInfo: InvalidOperation: (ApplyTo:String) [], RuntimeException

    +FullyQualifiedErrorId:InvokeMethodOnNull

    I'm a novice programmer and particularly novice on Powershell. I'm not sure I understand what the problem is or how to fix it.

    I'd appreciate any help.

    Friday, December 27, 2013 4:07 PM

Answers

  • So are you saying this is an alternative approach to the code you suggested before?  But that it doesn't apply it to all the sites?

    You are not using the terminology correctly which will confuse you.

    A site has 'Webs'.  We also can have site collections.

    Learning the fundamentals of PowerShell and SharePoint will help.

    Here is an example of applying a theme to all webs in a site and using the CmdLet to do the heavy lifting.

    $site=Get-SPSite -Identity $siteURL
    $themename='Yoshi'
    $theme=[Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catalogs/theme/$themeName.thmx")
    $sites.AllWebs | 
         ForEach-Object{
              $theme.ApplyTo($_,$false)
         }
    
    

    This, of course, also requires exception handling.


    ¯\_(ツ)_/¯

    • Marked as answer by DonCu Monday, December 30, 2013 5:29 PM
    Monday, December 30, 2013 5:07 PM

All replies

  • I think this is closer to what you are trying to do:

    function Apply-SPTheme{
          Param(
              [string]$SiteUrl, 
              [string]$webName='', 
              [string]$themeName
         )
        $site = new-object Microsoft.SharePoint.SPSite($SiteUrl)
         Try{
              $web=$Site.OpenWeb($webName)
              $theme=[Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catatlogs/theme/$themeName.thmx")
              $theme.ApplyTo($web,$false)
              $web.Update()
              $web.Dispose()
              $site.Dispose()
         }
         Catch{
             Throw $_
         }
    }
    
    Apply-SPTheme -SiteUrl https://sitename  -themeName themeName


    ¯\_(ツ)_/¯

    Friday, December 27, 2013 8:57 PM
  • Thanks much for your help.  I tried to run your script as written, except adding my site URL and the particular theme name.  I continue to get the message "You cannot call a method on a null-valued expression.  It appears to be related to the phrase ($web,$false).  Is this saying that it is going to the first subsite and not finding anything?  Have I somehow given the incorrect URL?  I put in the http URL listed in Central Admin.  I have also put in the secure https URL.  Not sure what my problem is.
    Monday, December 30, 2013 2:06 PM
  • It is telling you that $theme is null. The object is null. There is no such theme on you server

    Run this manually to see what I am pointing out:

    $site=...<get a site here at a prompt>

    [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catatlogs/theme/$themeName.thmx")

    If this returns null then be sure you have that theme installed.  It is not being found. 


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 3:40 PM
  • Try like this

    function Apply-SPTheme([string]$SiteUrl, [string]$webName, [string]$themeName)
    {
     $site = new-object Microsoft.SharePoint.SPSite($SiteUrl)
     $web = $Site.OpenWeb($webName)
     $theme = [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catatlogs/theme/" + $themeName + ".thmx")
     $theme.ApplyTo($web,$false)
     $web.Update()
     $web.Dispose()
     $site.Dispose()
    }
    Apply-SPTheme "https://sitename" -themeName "themeName" -webName " "


    Regards Chen V [MCTS SharePoint 2010]

    Monday, December 30, 2013 3:46 PM
  • Chen - Once again you are duplicating my post from two days ago.  You are missing the issue that using a try/catch block has uncovered and have just duplicated the users mistakes.

    Look very closely at the code.  It has an error.  Your code duplicates the error and will also miss it. 

    I also purposely exaggerated the error point to try and see if that would change the error.  It doesn't. 


    ¯\_(ツ)_/¯


    • Edited by jrv Monday, December 30, 2013 3:51 PM
    Monday, December 30, 2013 3:49 PM
  • Chen - Once again you are duplicating my post from two days ago.  You are missing the issue that using a try/catch block has uncovered and have just duplicated the users mistakes.

    Look very closely at the code.  It has an error.  Your code duplicates the error and will also miss it.


    ¯\_(ツ)_/¯

    Duplicating? What does that mean? Sorry jrv.

     $theme.ApplyTo($web,$false)

    Over here the variable $web is null. If I am not wrong that is the issue here - Let me test in my environment


    Regards Chen V [MCTS SharePoint 2010]

    Monday, December 30, 2013 3:53 PM
  • Here is how to enumerate themes on a site:

    [Microsoft.SharePoint.Utilities.ThmxTheme]::GetManagedThemes($site)

    Be sure the theme you are asking for actually exists at that path.  Copy and pasted it into the code to be sure it will load.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 3:59 PM
  • here is an updated version that checks for a missing theme:

    function Apply-SPTheme{
          Param(
              [string]$SiteUrl, 
              [string]$webName='', 
              [string]$themeName
         )
        $site = new-object Microsoft.SharePoint.SPSite($SiteUrl)
         Try{
              $web=$Site.OpenWeb($webName)
              if($theme=[Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catatlogs/theme/$themeName.thmx")){
                   $theme.ApplyTo($web,$false)
              }else{
                   Write-Host 'Theme not found!' -fore red
              }
              $web.Update()
         }
         Catch{
             Throw $_
         }
         Finally{
              $web.Dispose()
              $site.Dispose()
         }
    }
    
    Apply-SPTheme -SiteUrl https://sitename  -themeName themeName

    The error is telling you that the theme was not found so it cannot be applied. This will report on a missing theme.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:02 PM
  • This worked for me

    $siteurl = “http://sitename.xx.com”
    $themeName = “any available theme name”
    $site = new-object Microsoft.SharePoint.SPSite($siteurl)
    $web = $site.OpenWeb()
    $theme = [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,”_catalogs/theme/” + $themeName + “.thmx”)
    $theme.ApplyTo($web,$false)
    $web.Update()
    $web.Dispose()
    $site.Dispose()


    Regards Chen V [MCTS SharePoint 2010]

    Monday, December 30, 2013 4:13 PM
  • Here is a version that catches all of the errors correctly.

    function Apply-SPTheme{
          Param(
              [string]$SiteUrl='', 
              [string]$webName='', 
              [string]$themeName='Yoshi'
         )
         Try{
              $site = new-object Microsoft.SharePoint.SPSite($SiteUrl)
              $web=$Site.OpenWeb($webName)
              if($theme=[Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catalogs/theme/$themeName.thmx")){
                   $theme.ApplyTo($web,$false)
                   Write-Host 'Theme applied' -fore green
              }else{
                   Write-Error -Message 'Theme not found!'
              }
              #$web.Update()
         }
         Catch{
             Throw $_
         }
         Finally{
              Write-Host 'Disposing' -fore green
              $web.Dispose()
              $site.Dispose()
         }
    }
    
    Apply-SPTheme -SiteUrl https://sitename  -themeName themeName


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:15 PM
  • Chen.  Again - we were there already.  We must hanle erros whenusing the APIs directly or you will get cascading errors and it can have nasty consequences.

    Code working once is not proof of functionality.

    If anything is wrong in the code it will run through a whole list of errors and attempt to update the site anyway. Using the mistakes to test the error catching helps to make the code workable.

    You also found the typos which now makes the code appear to work until a bad them is asked for.  Try using  a bad theme.

    Also, without the exception handler "dispose" will never be called.  Using 'Finally' guarantees that the dispose will be called.

    PowerShell should call dispose when the object is discarded on exit of the function but it may not on this API.  PS attempts to call dispose on all objects when cleaning up but I am not sure that that means ALL objects or just all PowerShell objects.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:21 PM
  • I agree and appreciate the exceptional method you used. Indeed I got an error with the wrong theme. Thanks for the explanation again jrv!!!

    Regards Chen V [MCTS SharePoint 2010]

    Monday, December 30, 2013 4:24 PM
  • I put those 2 lines in a script and ran it.  I get the blank prompt in return.  My SharePoint site does show the theme, called CorpTheme present and as the current theme.
    Monday, December 30, 2013 4:35 PM
  • I agree and appreciate the exceptional method you used. Indeed I got an error with the wrong theme. Thanks for the explanation again jrv!!!

    Regards Chen V [MCTS SharePoint 2010]

    The problem here is that there are multiple errors and typos and the code is directly accessing the API which has no error management.

    On SharePoint 2007 and later users should stick to the provided CmdLets if they are not experienced with coding. I understand that the cCmdLets still have few examples at this point.

    The code example I posted helps but it still does not plug all of the holes.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:37 PM
  • I put those 2 lines in a script and ran it.  I get the blank prompt in return.  My SharePoint site does show the theme, called CorpTheme present and as the current theme.

    what two lines?

    If you do this does it show your theme?

    [Microsoft.SharePoint.Utilities.ThmxTheme]::GetManagedThemes($site)


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:40 PM
  • Again:

    [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catatlogs/theme/$themeName.thmx")

    Look closely at this. It is an exact copy of your code and is one of 3 or more subtle errors:

    Set $site and $themename and test.  Look closely at the path and how it is spelled.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:42 PM
  • I really appreciate your patience. How do I make it give me a chance to look a page at a time?  I get a result but it is alphabetically past CorpTheme.
    Monday, December 30, 2013 4:45 PM
  • First you need to learn the basics of PowerShell. 

    Use 'select-object' to return only the elements you are loomingfor.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:53 PM
  • If we use the built in CmdLets we can simplify most of this on 2010.

    $web=Get-SPWeb http://companyweb
    $themename='Yoshi'
    $theme=[Microsoft.SharePoint.Utilities.ThmxTheme]::Open($web.site,"_catalogs/theme/$themeName.thmx")
    $theme.ApplyTo($web,$false)

    Using this there is no need to dispose of anything and only a need to get the web. The site comes as a free bit.

    This would also require exception handling but is is much simpler.

    What we haven't attacked is how to enumerate the webs in a collection.


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 4:56 PM
  • You're absolutely right about that.  In any event, I'm getting a list of the themes but I can't go back alphabetically to where I'd find CorpTheme, if it was there.  I looked up and tried the |more command, but that didn't work.  I'll look up select object.
    Monday, December 30, 2013 4:57 PM
  • So are you saying this is an alternative approach to the code you suggested before?  But that it doesn't apply it to all the sites?
    Monday, December 30, 2013 5:01 PM
  • So are you saying this is an alternative approach to the code you suggested before?  But that it doesn't apply it to all the sites?

    You are not using the terminology correctly which will confuse you.

    A site has 'Webs'.  We also can have site collections.

    Learning the fundamentals of PowerShell and SharePoint will help.

    Here is an example of applying a theme to all webs in a site and using the CmdLet to do the heavy lifting.

    $site=Get-SPSite -Identity $siteURL
    $themename='Yoshi'
    $theme=[Microsoft.SharePoint.Utilities.ThmxTheme]::Open($site,"_catalogs/theme/$themeName.thmx")
    $sites.AllWebs | 
         ForEach-Object{
              $theme.ApplyTo($_,$false)
         }
    
    

    This, of course, also requires exception handling.


    ¯\_(ツ)_/¯

    • Marked as answer by DonCu Monday, December 30, 2013 5:29 PM
    Monday, December 30, 2013 5:07 PM
  • I agree that I have much to learn in both spheres.  What does enumerate mean in this context?
    Monday, December 30, 2013 5:16 PM
  • I tried this script.  At first I didn't think it worked, because the page on the site looked the same as it did.  However, when I went into the site themes, CorpTheme was there.  I was thinking it would change all the themes, but, it appears to make it available to all the sites, which is great!  Thank you for your time and patience.  I was put in charge of building my company's intranet site 6 months ago with no knowledge of SharePoint, much less Powershell and no budget for training.  So I generally learn as I have to do something.  So you are right, I have much to learn.  Can you recommend an on-line place with tutorials for Powershell?  I'm doing the best I can.  Thank goodness for people like you who know what you are doing.
    Monday, December 30, 2013 5:29 PM
  • This is Good Book

    Regards Chen V [MCTS SharePoint 2010]


    • Edited by Chen VMVP Monday, December 30, 2013 5:35 PM
    Monday, December 30, 2013 5:31 PM
  • don.sander@hfcuvt.com

    Thanks a lot!

    Monday, December 30, 2013 5:35 PM
  • I have shared all the materials!!!

    Regards Chen V [MCTS SharePoint 2010]

    Monday, December 30, 2013 5:37 PM
  • I highly recommend going back to the SharePoint 2010 site and going through all of the fundamentals.  If yo allocate an hour a day you should be caught up in two weeks.  This will save you hundreds of hours of fishing for solutions.

    SharePoint is far too complex to be "guessed" at.  You will never guess at its structure. Going through the basics from the ground up will burn the structure of its design into you head.  You will then be able to find answers quickly because you will know the documentation and how to ask the questions.

    If you are only a basic Admin then your company should allow the vendor to either do the configurations or pay for you to be trained or compensate you to use your personal time for training.  It would be a win for them.

    There are many very good books on SharePoint and PowerShell.  They are only good if you already have the basics of both.  One that I acquired recently is quite good at you level of involvement as it is a cookbook of solutions in PowerShell for normal configuration and administration items that goes beyond what is available on the web site or in the basic training.

    http://www.wrox.com/WileyCDA/WroxTitle/productCd-0470533331.html

    I actually have the 2013 version but you should stick to the 2010 version until you are up to speed.  I bought 2013 as a catch up.  Read it over two long dinners of Sushi and Sake.

    The books run the gamut of SP from planning to admin.  They are not technical manuals and not developer books.  They are written for general administration,  You will read through quickly and then refer back to chapters as needed.  As your SP site evolves the book will help you evolve with it.

    Start by becoming extremely familiar with all of the resources on the SharePoint 2010 product site.  Post future requests that are SharePoint related to the SP forums.  They are very good with PowerShell at this time (three versions but they seem to have caught up) - They know the product better than most here and are closer to the MS MVPs on SharePoint.  If there is a pure PowerShell issue then the people in this forum can very helpful,

    Here are all of the SharePoint forums: http://social.msdn.microsoft.com/Forums/sharepoint/en-US/home?filter=alltypes&sort=lastpostdesc&brandIgnore=true


    ¯\_(ツ)_/¯

    Monday, December 30, 2013 6:09 PM
  • Thanks again.  I appreciate your thoughtful comments.
    Monday, December 30, 2013 6:22 PM