PowerShell + MOSS…Am I 4 Years behind or What

I have to admit it, I am a huge PowerShell fan. I have been playing with it using SharePoint 2010 for a few months now, and I just love it. To me, PowerShell is a way to clearly demonstrate to the people installing our SharePoint releases exactly what is going on in the background. The company I work for uses SharePoint as a case management tool. Every modification we make to a Web, needs to be applied for any new site being created from that point on, but also needs to be retro-actively applied on all pre-existing ones. They are using MOSS 2007 Entreprise x86 running on Windows Server 2003 x86 as their infrastructure.

Until now, every time a change had to be applied to a Web, I have been telling the developers to do 2 things. First, to modify the logic in the assembly responsible of creating the new webs so that it applies the change at creation time. Second, I’ve been asking them to write an executable that was to be run on the server directly, and that was looping through all pre-existing webs to make the change retro-actively.  Problem with that approach is that our Infrastructure team, in charge of installing our releases onto our production server, don’t have a clue what those executable are doing in the background (those IT Pro guys never trust what developers do right?).

To remediate to the situation, I have decided to bring my team up to date with PowerShell, and am now asking them to script their retro-active changes into a PS1 script. Now, Windows Server 2003 only supports PowerShell 1, so our scripts have to be a little bit more complex, but not to worry, it’s close enough with what the PowerShell + SharePoint 2010 experience will look like. Nobody should get lost when they finally make the switch to SP 2010 in a couple of months from now.

Our PowerShell scripts that loop through all webs are really easy to understand, and they look just like C# code would look like when programming against the SharePoint object model.

#Nik20110119 – Get a reference to the SharePoint 2007 Assembly

#Nik20110119 – Get an instance of the default Web Application
$spwebapp=[Microsoft.SharePoint.Administration.SPWebApplication]::Lookup(“http://[root url of the webapplication]“)
#Nik20110119 – Loop through all sites at the Web Application Level;
foreach($spsite in $spwebapp.Sites)
#Nik20110119 – Loop through all webs inside the current Site Collection;
$sproot = $spsite.OpenWeb()
foreach($spweb in $sproot.Webs)
# Nik20110119 – Perform all logic on the SPWeb objects here. T get full list of properties and methods, simply pipe the $spweb variable into the get-member method;

When Inheritance Resets Security

If you’ve ever tried to play with sites permissions via the SharePoint Object Model, you’ve probably encountered this nasty security validation error:

The security validation for this page is invalid.

An easy work around for this, is to temporarily allow unsafe updates to be done at the web level by setting the following property to true:

[SPWeb].AllowUnsafeUpdates = true;

Well, guess what, depending on what you are trying to achieve with your code, you may have to set this value to true more than once during the lifetime of your SPWeb object. Whenever you code is breaking inheritance on a RoleDefinition that exists at the web level, this property automatically gets reset to false. For example, the following code, where elevatedWeb is an elevated SPWeb object:

elevatedWeb.AllowUnsafeUpdates = true;Opened Lock

SPMember member = elevatedWeb.Users[“contoso\userx];

SPRoleDefinitionCollection roledef = elevatedWeb.RoleDefinitions;

if (!elevatedWeb.HasUniqueRoleDefinitions)
roledef.BreakInheritance(true, true);

Automatically resets the AllowUnsafeUpdates property to false as soon as the .BreakRoleInheritance is called on the RoleDefinition. Not that, however, it is not being reset when the inheritance is broken on the elevatedWeb SPweb object This is something to watch out for.