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!

Wednesday, August 10, 2011

SharePoint Saturday The Conference – SharePoint and PowerShell unite!

This weekend SharePointers aplenty will converge on our nations capitol for three days SharePointy goodness. I fly out here in a couple hours to join them!

I had planned to write up a longer more descriptive post about the sessions I will be giving and why you should come see them but alas I was too busy making last minute updates to my demo VMs to really do them justice. Instead you get this.

Below are the agenda slides from my two sessions. I hope you will come out and learn the joys of SharePoint!

Taming the Beast: A SharePoint Survival Guide for the Server Admin

SPSTCDC_Taming_The_Beast

Applied PowerShell: PowerShell for the SharePoint Server Admin

SPSTCDC_Applied_PowerShell

Full schedule can be found here: http://www.spstc.org/blog/Lists/Posts/Post.aspx?ID=38

Saturday, May 14, 2011

Microsoft Tags = Really freaking cool!

So, I am headed to TechEd  this week and they are having a scavenger hunt with Microsoft Tags. I had seen the app in the Windows Phone marketplace but had not actually taken a look at it. I must say I’m really impressed.

If you are going to be in Atlanta for TechEd grab the free Microsoft Tag from here and join me in the scavenger hunt.

Once you have grabbed you can test it on the Tag below.

CraigToThePointTag

Have fun and if you are going to be there give me a shout!

PowerShell to remove web parts with errors from SharePoint 2010

One of the things that I run into whenever I do an upgrade from an older version of SharePoint to SharePoint 2010 is that not all of the custom functionality previously implemented still works. This is especially true when moving from WSS 2.0 to SharePoint 2010.

When a client has 50+ sites and these web parts are on every landing page the process of removing them manually is just out of the questions. So how do we solve this?

Well, in SharePoint 2007 I would have said that you should go bug a developer and have them write you a console application to loop through and remove any and all erroring web parts. However, in SharePoint 2010 the story is slightly different.

PowerShell to the rescue!!!

function Remove-SPErroringWebParts
{
[CmdletBinding()]

param
(
[parameter(ValueFromPipeline=$true,Mandatory=$true,Position=0)]
$Web
)

begin
{
Out-Host -InputObject "Beginning Remove-SPErroringWebParts..."
}

process
{
if ($Web -is [string]) {Out-Host -InputObject " This is a string.";$Web = Get-SPWeb $Web}
if ($Web -is [Microsoft.SharePoint.Administration.SPWebApplication]) {Out-Host -InputObject " This is a web app.";$Web = Get-SPSite -WebApplication $Web -Limit All -Confirm:$false}
if ($Web -is [Microsoft.SharePoint.SPSite[]]) {Out-Host -InputObject " This is an array of sites.";$Web | %{Set-AllBackToSiteDefinition -Web $_}}
if ($Web -is [Microsoft.SharePoint.SPSite] ) {Out-Host -InputObject " This is a site.";$Web = (Get-SPWeb -Site $Web -Limit All -Confirm:$false)}
if ($Web -is [array]) {" This is an array."; $Web | %{ Remove-SPErroringWebParts $_ } }
if ($Web -is [microsoft.SharePoint.SPWeb])
{
Out-Host -InputObject " This is a web."
$webpartmanager = $Web.GetLimitedWebPartManager(($Web.Url + "/default.aspx"), [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)

#Create a separate list of webparts to be deleted to avoid enumeration error
$webpartsToDelete = $webpartmanager.WebParts | ?{$_.ErrorMessage -ne $null}

foreach ($webpart in $webpartsToDelete)
{
if ($webpart.ErrorMessage -ne $null)
{
Out-Host -InputObject " Deleting webpart.."
$webpartmanager.DeleteWebPart($webpart)
}
}
$Web.Dispose()
}
}

end
{
Out-Host -InputObject "Finished Remove-SPErroringWebParts."
}
}



The function above looks far more complicated than it really is. I wrote it so that I could save it off and use it for later projects. To be honest, this function isn’t really done as I need to add a great deal of error handling, it only checks the “/default.aspx” page so if you have Publishing sites or even sites that use the Wiki Home Page it will not work, and there is some Out-Host commands that will most likely be changed to Out-Debug. However, I digress. Writing PowerShell for reusability is a completely different discussion that I will probably write about at a later date. Until then there are a couple really great blog posts you can check out if you are interested:




For now, lets take a look at what a more minimalistic approach would be.




$Web = Get-SPWeb "http://site/web"
$webpartmanager = $Web.GetLimitedWebPartManager(($Web.Url + "/default.aspx"), [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$webpartsToDelete = $webpartmanager.WebParts | ?{$_.ErrorMessage -ne $null}
foreach ($webpart in $webpartsToDelete)
{
if ($webpart.ErrorMessage -ne $null)
{
Out-Host -InputObject " Deleting webpart.."
$webpartmanager.DeleteWebPart($webpart)
}
}
$Web.Dispose()



Much less code there but less power as well. This will obviously only work on an SPWeb object and the code would need to be adjusted for any other scope. Let’s take a look at the usage of the original function.

On an SPWeb object:




Get-SPWeb "http://server/site/web" | Remove-SPErroringWebParts


On an SPSite object:


Get-SPSite "http://server/site" | Remove-SPErroringWebParts


On an SPWebApplication object:


Get-SPWebApplication "http://server" | Remove-SPErroringWebParts


Or on an string:


"http://server/site/web" | Remove-SPErroringWebParts





Either way the function will loop through all of the “/default.aspx” pages on the SPWeb objects of the given scope and remove any web parts that have errors.

I’m sure I don’t have to tell you that this can be just as dangerous as it is helpful if you have web parts that are erroring that you are not aware of. As always use caution and I’m not responsible for anything you break while using anything you find here. Smile


I hope this helps! Any and all feedback is welcomed and appreciated. Let me know what you think!

Friday, May 13, 2011

Sign on as different user to SharePoint 2010 site published through TMG 2010

As of Service Pack 1, TMG now officially supports publishing SharePoint 2010 sites. If you have tried this you may have ran into an issue when trying to use the “Sign in as Different User” functionality. Fortunately Microsoft has released an update that resolves the issue.

http://support.microsoft.com/kb/2445386

The update is included in Software Update 1 rollup 3 for TMG SP1. This rollup can be found here:

http://support.microsoft.com/kb/2498770

However, just having applied the rollup does not solve the issue.  You will also need to run one of the following scripts on one of your TMG front ends.

For HTML Forms Authentication with Kerberos Constrained Delegation:

Const SE_VPS_GUID = "{143F5698-103B-12D4-FF34-1F34767DEabc}"
Const SE_VPS_NAME = "EnableSharepointSignIn"
Const SE_VPS_VALUE = true

Sub SetValue()

' Create the root object.
Dim root ' The FPCLib.FPC root object
Set root = CreateObject("FPC.Root")

'Declare the other objects that are needed.
Dim array ' An FPCArray object
Dim VendorSets ' An FPCVendorParametersSets collection
Dim VendorSet ' An FPCVendorParametersSet object

' Get references to the array object
' and to the network rules collection.
Set array = root.GetContainingArray
Set VendorSets = array.VendorParametersSets

On Error Resume Next
Set VendorSet = VendorSets.Item( SE_VPS_GUID )

If Err.Number <> 0 Then
Err.Clear

' Add the item.
Set VendorSet = VendorSets.Add( SE_VPS_GUID )
CheckError
WScript.Echo "New VendorSet added... " & VendorSet.Name

Else
WScript.Echo "Existing VendorSet found... value- " & VendorSet.Value(SE_VPS_NAME)
End If

if VendorSet.Value(SE_VPS_NAME) <> SE_VPS_VALUE Then

Err.Clear
VendorSet.Value(SE_VPS_NAME) = SE_VPS_VALUE

If Err.Number <> 0 Then
CheckError
Else
VendorSets.Save false, true
CheckError

If Err.Number = 0 Then
WScript.Echo "Done with " & SE_VPS_NAME & ", saved!"
End If
End If
Else
WScript.Echo "Done with " & SE_VPS_NAME & ", no change!"
End If

End Sub

Sub CheckError()

If Err.Number <> 0 Then
WScript.Echo "An error occurred: 0x" & Hex(Err.Number) & " " & Err.Description
Err.Clear
End If

End Sub

SetValue





For Integrated Authentication with Kerberos Constrained Delegation: You will need to run the script above as well as the script below.




Const SE_VPS_GUID = "{143F5698-103B-12D4-FF34-1F34767DEabc}"
Const SE_VPS_NAME = "UseOnlyNTLMForWindowsAuth"
Const SE_VPS_VALUE = 1

Sub SetValue()

' Create the root object.
Dim root ' The FPCLib.FPC root object
Set root = CreateObject("FPC.Root")

'Declare the other objects that are needed.
Dim array ' An FPCArray object
Dim VendorSets ' An FPCVendorParametersSets collection
Dim VendorSet ' An FPCVendorParametersSet object

' Get references to the array object
' and to the network rules collection.
Set array = root.GetContainingArray
Set VendorSets = array.VendorParametersSets

On Error Resume Next
Set VendorSet = VendorSets.Item( SE_VPS_GUID )

If Err.Number <> 0 Then
Err.Clear

' Add the item.
Set VendorSet = VendorSets.Add( SE_VPS_GUID )
CheckError
WScript.Echo "New VendorSet added... " & VendorSet.Name

Else
WScript.Echo "Existing VendorSet found... value- " & VendorSet.Value(SE_VPS_NAME)
End If

if VendorSet.Value(SE_VPS_NAME) <> SE_VPS_VALUE Then

Err.Clear
VendorSet.Value(SE_VPS_NAME) = SE_VPS_VALUE

If Err.Number <> 0 Then
CheckError
Else
VendorSets.Save false, true
CheckError

If Err.Number = 0 Then
WScript.Echo "Done with " & SE_VPS_NAME & ", saved!"
End If
End If
Else
WScript.Echo "Done with " & SE_VPS_NAME & ", no change!"
End If

End Sub

Sub CheckError()

If Err.Number <> 0 Then
WScript.Echo "An error occurred: 0x" & Hex(Err.Number) & " " & Err.Description
Err.Clear
End If

End Sub

SetValue





Once this is complete you should be able to Log in as a Different User to your hearts content.



I hope this helps!

Thursday, October 29, 2009

WSS and MOSS October CU Released

The October cumulative update for WSS 3.0 and MOSS 2007 has been released yesterday here are the KB article links for these fixes:

The fixes can be downloaded using the following links:

Monday, October 19, 2009

SharePoint 2010 – And the Downloadable Content keeps coming!!!

The content keeps trickling in. Microsoft has been releasing posters all day, (http://ctrulove.blogspot.com/2009/10/sharepoint-2010-posters-for-everyone.html) but wait, there’s more!

More POSTERS!!!!

SharePoint 2010- SharePoint Developer Platform Wall Poster - The SharePoint 2010 Developer Platform wall poster (PDF format) shows a view of the SharePoint 2010 developer tools, community ecosystem, execution environment, SharePoint Server 2010 workloads, and target application types. The poster is intended to be printed at 24 inches x 36 inches (61 centimeters x 91 centimeters).

SharePoint 2010- Developer Platform White Paper - This white paper provides an overview of the SharePoint 2010 Developer Platform for ASP.NET developers.

Enterprise Search Planning for SharePoint Server 2010 - This model describes primary architecture design decisions for search environments.

Design Search for SharePoint Server 2010 - This model describes the steps to determine a basic design for a SharePoint Server 2010 search architecture.

SharePoint Server 2010 Search Architecture - This model describes the physical and logical architecture components of the search system.

 

Learning and Evaluation Stuff Too!!!

SharePoint 2010- Getting Started with Development on SharePoint 2010- Hands on Labs in C# and Visual Basic - Use these 10 hands-on lab manuals for SharePoint 2010 to get started learning SharePoint 2010 development.

SharePoint 2010- Developer and IT Professional Learning Plan - This document provides information to help developers and IT professionals learn Microsoft SharePoint 2010.

SharePoint 2010- Professional Developer Evaluation Guide and Walkthroughs - The SharePoint 2010 developer evaluation guide describes the SharePoint 2010 developer platform, including walkthroughs of some of the new capabilities for developers.

SharePoint Server 2010 Evaluation Guide - Introduction and overview of SharePoint Server 2010 for IT pros.

I am sure there is more to come. Enjoy!