Yesterday I wrote my first PowerShell script. During that process I’ve discovered quite a few things – new to me being a .NET developer.
Load your assemblies on time
All the assemblies required by the script must be loaded before the script is executed. Consider the following script for example:
param(
[string]$Url = $(Read-Host -prompt "Site (Collection) Url"),
[bool]$Recursive = $false
)
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
function Get-SPFolder
{
param (
[Microsoft.SharePoint.SPWeb]$Web,
[string]$FolderName
)
}
As soon as PowerShell finds a reference to a type located in the Microsoft.SharePoint assembly, it will throw an error: Unable to find type [Microsoft.SharePoint.SPWeb]: make sure that the assembly containing this type is loaded. You have to be sure that all assemblies required by your script have been loaded prior to executing your script.
Passing parameters to scripts/functions
What makes PowerShell scripts really useful is to make them reusable. And to do that you have to make your scripts accept parameters. As a C# developer you might want to try to define a PowerShell function like this:
function Get-SPFolder([Microsoft.SharePoint.SPWeb]$Web, [string]$FolderName)
{
}
While it won’t result in an error it definitely isn’t correct. Instead of defining the function’s parameters, it makes an array out of some variables. You shouldn’t be surprised if you get errors later on while working on such “parameters”.
PowerShell allows you to refer to passed parameters either through their names:
function Get-SPFolder
{
param(
[Microsoft.SharePoint.SPWeb]$Web,
[string]$FolderName
)
}
or through the args array using the parameter’s position:
function Get-SPFolder
{
$Web = $args[0]
$FolderName = $args[1]
}
By default all parameters are optional. PowerShell allows you to specify what kind of parameters you want to use in your script/function:
function Get-Something
{
param (
[string] $OptionalParameter,
[string] $OptionalParameterWithDefaultValue = "Default",
[string] $RequiredParameter = $(throw "Required parameter -RequiredParam missing"),
[string] $PromptParameter = $(Read-Host -prompt "Prompt parameter:", # prompts for value if none provided
[switch] $SwitchParameter # optional flag parameter
)
}
Param – first things first
In order for param to work correctly it has to be the very first thing in your script function. Consider the following function:
function Get-SPFolder
{
$folder = $null;
param(
[Microsoft.SharePoint.SPWeb]$Web,
[string]$FolderName
)
}
If you execute it you will get the following error: The term 'param' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again. You can easily fix the issue by moving the param up:
function Get-SPFolder
{
param(
[Microsoft.SharePoint.SPWeb]$Web,
[string]$FolderName
)
$folder = $null;
}
Typing variables
In PowerShell you can use untyped variables like:
$myvar = "foo"
Optionally you can provide the type of your variables:
[string] $myvar = "foo"
Although optional I found it to be a very useful thing especially when debugging your script.
What was the script again?
As I mentioned I found out all the things described here while working on a PowerShell script. In the SharePoint project I’m working on at the moment, the customer requested a Theme to meet his branding requirements. The initial release as well as stapling the Theme to different Site Definitions was quite straight-forward. In the second release however, we had to do some changes to the Theme.
If you’ve ever worked with SharePoint Themes you know that right after you apply a Theme to a Site, SharePoint creates a copy of the Theme and stores it in the _themes folder. Because it’s a copy instead of a reference none of your changes is being reflected on the Site. In order to provision the changes to the Site you have to delete the _themes folder and reapply the Theme. While it is something you could do in numerous ways, it seemed to me like a good candidate for a PowerShell script.
Download Set-Theme.ps1 from CodePlex (2KB, PS1)
Learning tip
Just recently fellow SharePoint MVP Matthew McDermott blogged about a free PowerShell e-book written by a PowerShell MVP Dr. Tobias Weltner. The book Mastering PowerShell is definitely worth reading as it covers both the basics as well as some advanced topics of working with PowerShell.
Summary
PowerShell is a great scripting language with countless possibilities. Leveraging it strength can simplify various administration and maintenance tasks of your environment. Also if you’re a developer you can benefit of PowerShell in your everyday’s work. Hopefully the things I’ve described above will help you set the first steps in the world of PowerShell.
















September 1st, 2009 at 9:00 am
So where\'s this cool PowerShell script for updating a theme then?
Great explanation, same pains I went through when learning PoSH.
September 1st, 2009 at 9:06 am
@Jeremy: Wanted to check if anybody would be interested in it first
I will publish it later today and ping you once it's available on-line.
September 1st, 2009 at 9:59 am
As always….LEGEND.
To "push some buttons"…if this is a limitations of Site Themes, why not do branding via Master pages, Page Layouts and Style sheets in 12 hive file system? And block unghosting
September 1st, 2009 at 10:09 am
@Jeremy: For a couple of reasons, like time (easier to modify a few CSS than to provide a whole new branding which would do the same) and support (WSS doesn't support Master Pages out of the box. Of course you can get it done but then the customer wouldn't be able to change it himself, etc, etc)
September 1st, 2009 at 10:25 am
Just came across my first client who has leveraged Site Themes and for each Sub -site the _themes directory is there so if they change branding for all sites, have to update EACH _themes sub site. Obviously your script would resolve this.
Fully understand that approach for that scenario though.
I agree, 12 Hive = WSP = Visual Studio really, so making changes isn't Content Author centric. But running PoSH scripts isn't either
September 1st, 2009 at 11:15 am
Just did a talk at TechEd on this topic and one before for the local community, both with Nicolas Blank (Exchange MVP).
Most SharePoint Devs are fast adopting this as essential part of their SDLC.
Powershell – Don't leave home without it
September 1st, 2009 at 12:48 pm
@Zlatan: absolutely. I was more of a Console-Application guy, having more than 80 of them in every VPC doing anything from retrieving properties to querying things. PowerShell is so much easier. Now I only need a good Win client with intellisense for all assemblies and I'll never touch Console Apps again
September 1st, 2009 at 6:48 pm
Idera has a cool IDE called PowerShell Plus. I've only briefly touched it (only 1 week trial). I've seen a demo of it and it's cool, tho you still have to know what you're doing (just like in VS, of course).
I really need to get my PoSH spice, er, I mean skills, together.
September 1st, 2009 at 7:20 pm
@Sherman: Thanks, I will definitely have a look at PowerShell Plus
September 9th, 2009 at 3:35 pm
We avoided this issue by referencing our custom theme-css-files (stored inside e.g. layouts/Customer.Theme/default.css) from inside the css-file inside the _themes-folder.
Because the css-file (of the theme) just @imports the css from the layouts-folder changes are very very easy.
September 9th, 2009 at 6:33 pm
@Eric: I've heard about that approach as well unfortunately a little too late. Still, it's definitely something I will keep in mind while working with themes. Thanks for the tip