Thursday, August 18, 2011

Fun with SharePoint and PowerShell: Part 1 of ?

I gave a session at SharePoint Saturday the Conference in DC last weekend called “Applied PowerShell: PowerShell for the SharePoint Server Admin”. (I know it is an annoyingly long name, but I’m not really that creative.) The session basically consisted of me talking about and demonstrating a bunch of really cool things I had learned to do with PowerShell as it pertained to SharePoint.

I’ve been meaning to write a blog post with all of the slides and scripts that I showed during the session but it is an overwhelming large amount of content and I keep putting it off. So, I have decided to meet you (my imaginary reader) half way and do it over the course of several blog posts.

This is not a planned series and I have no idea how may parts there will be. But hey, I know this is part 1. Smile

Script 1: Applying a Theme to One or More Sites/Webs

Disclaimer for those who actually attended fore mentioned session: No, this wasn’t actually covered. Deal with it. Smile with tongue out

Let me start by saying that I don’t really like themes in SharePoint. I work for a company (http://www.northridge.com) that has a design team in house and makes really cool master pages and so I prefer not to resort to themes. However, sometimes you are stuck with OOTB and I get that. If you happen to be stuck with OOTB, themes got much cooler with SharePoint 2010. You can actually take a PowerShell theme and upload it to the Theme Gallery and apply it to your site.

This is because SharePoint 2010 now uses .thmx files for it’s themes. To prove my point see screen shots below:

image image

SharePoint 2010

PowerPoint 2010

I know what you’re thinking, “But Craig, I already knew all of that where is the script?!?!”. Well, it is important to understand that if you are going to do a custom them (not one of the ones that come OOTB) then you will need a THMX file to apply. So lets fast forward and assume you already have a THMX file and you want to apply that to your site(s).

There are two basic steps: add the THMX file to the Theme Gallery, and set the web to use said theme.

Step 1: Add the Theme to the Theme Gallery

This step is pretty straight forward. We just need to add a file to the gallery. I’ve written a simple function that is generic and adds a file from the file system to a specified document library within a given web. Let’s take a look:

function Add-SPFileToLibrary
{
param
(
[String] $file,
[Microsoft.SharePoint.SPWeb] $web,
[String] $LibraryName
)
$lib = $web.GetFolder($LibraryName)

# Prepare to upload
$replaceExistingFiles = $true
$fileName = [System.IO.Path]::GetFileName($file)
$fileStream = [System.IO.File]::OpenRead($file)

# Upload document
$spfile = $lib.Files.Add($fileName, $fileStream, $replaceExistingFiles);

# Commit
$lib.Update();
}




Cool! So, I just need to know what the library’s name is and then I should be good to go. Let’s take a look at the library’s that are provisioned by default in a web.







image


Hmm… that doesn’t seem to have what I need. Nothing that says theme at least. Lets take a look at all of the lists that get provisioned by default.








image



Ah ha! “Theme Gallery” looks like what I want. Lets investigate further!







image


Now we are making progress! From this I can see that the folder I am looking for is “_catalogs/theme”. Ok, let’s put it all together.




$site = Get-SPSite "http://nr01-crtru-lt01/"
Add-SPFileToLibrary -file "C:\Themes\MyNewTheme.thmx" -LibraryName "_catalogs/theme" -web $site.RootWeb
$site.Dispose()



A couple things to note about this. 1) The gallery only exists at the RootWeb of a site collection. 2) Always dispose of instantiated SPSite and SPWeb objects!



Ok, now the theme has been uploaded but it is still not applied to the site. Let’s do something about that.



Step 2: Apply the Theme


In the UI this is really easy. You go to Site Settings, click on Site Theme, choose your theme, and apply. In PowerShell the answer is not so obvious. If you do a little exploring with the Get-Member you may come across $web.Theme and think this is your answer. But alas, this is not the case. The theme property on SPWeb is actually a leftover from v3 themes from 2007. Definitely NOT what we want.



After some digging around on MSDN I ran across Microsoft.SharePoint.Utilities.ThmxTheme. This little utility class gives us access to serveral functions that when put together give us what we are looking for. I’ll spare you the painful iterations of getting to where we want to be and just give you the script.




# Get a collection of available themes
$managedThemes = [Microsoft.SharePoint.Utilities.ThmxTheme]::GetManagedThemes($site)

# Get my new theme
$theme = $managedThemes | Where-Object {$_.Name -eq "My New Theme"}

# Apply theme to root web
$theme.ApplyTo($site.RootWeb,$true)



Awesome! That applies it to the RootWeb but what about all my lonely sub webs that didn’t get it. Well, you can use this nifty trick to set them all to “inherit” the theme from their parent site.




# Loop through each web in the site
foreach ($web in $site.AllWebs)
{
# Make sure it is not the root web
if (-not $web.isRootWeb)
{
# Set sub webs to inherit from root
[Microsoft.SharePoint.Utilities.ThmxTheme]::SetThemeUrlForWeb($web,[Microsoft.SharePoint.Utilities.ThmxTheme]::GetThemeUrlForWeb($site.RootWeb))
}
$web.Dispose()
}
$site.Dispose()



Ok, that does it. Let’s put it all together so we can use it over and over again!




# Adds a file to given library
function Add-SPFileToLibrary
{
param
(
[String] $file,
[Microsoft.SharePoint.SPWeb] $web,
[String] $LibraryName
)
$lib = $web.GetFolder($LibraryName)

# Prepare to upload
$replaceExistingFiles = $true
$fileName = [System.IO.Path]::GetFileName($file)
$fileStream = [System.IO.File]::OpenRead($file)

# Upload document
$spfile = $lib.Files.Add($fileName, $fileStream, $replaceExistingFiles);

# Commit
$lib.Update();
}

# Applys a theme to an entire site collection
function Update-SPSiteTheme
{
param
(
$Path,
$Name,
$Site
)
# Add the theme to the Theme Gallery
Add-SPFileToLibrary -file $Path -LibraryName "_catalogs/theme" -web $site.RootWeb
# Get a collection of available themes
$managedThemes = [Microsoft.SharePoint.Utilities.ThmxTheme]::GetManagedThemes($site)
# Get my new theme
$theme = $managedThemes | Where-Object {$_.Name -eq $Name}
# Apply theme to root web
$theme.ApplyTo($site.RootWeb,$true)
# Loop through each web in the site
foreach ($web in $site.AllWebs)
{
# Make sure it is not the root web
if (-not $web.isRootWeb)
{
# Set sub webs to inherit from root
[Microsoft.SharePoint.Utilities.ThmxTheme]::SetThemeUrlForWeb($web,[Microsoft.SharePoint.Utilities.ThmxTheme]::GetThemeUrlForWeb($site.RootWeb),$true)
}
$web.Dispose()
}
$site.Dispose()
}



Obviously the function needs some work (error handling, comment based help, etc.) but it should get the job done. Give it a try and let me know what you think.



Enjoy!

No comments: