Downloads
140143.zip

As with any new release, there was a lot to learn when SharePoint 2010 hit the streets. There were new features to master, and there were even some old features with which to get reacquainted. Typically, I’m up for such a challenge. Heck, I revel in it. However, one of the biggest challenges that I almost didn’t overcome was learning Windows PowerShell.

I’ve been working with SharePoint for a long time now. Although I started with SharePoint Team Services 2001, I really cut my teeth with Windows SharePoint Services 2.0 (WSS 2.0). I used it to manage a farm that had more than 1,200 site collections and more than 10,000 subsites, which are often referred to as webs. I learned very early on to love and embrace scripting.

I became especially good friends with the Stsadm command-line tool. Stsadm allowed me to manage the large farm and still have plenty of time to watch hysterical cat videos on YouTube. I was able to capitalize on my friendship with Stsadm. I wrote a TechNet Magazine article on Stsadm, a book chapter on Stsadm, and spoke at TechEd on, you guessed it, Stsadm.

Stsadm has been very good to me. Imagine my shock and horror when I found out that SharePoint 2010 was going to transition to PowerShell and my beloved Stsadm was being deprecated. 

Until that moment in 2009, my exposure to PowerShell had been very limited. I had mostly avoided it because it seemed to “developery” for my tastes. It had objects, whatever those are. I’m a simple man. Stsadm, while limited and quirky, was easy to tame. PowerShell was complicated and bombastic. I honestly wasn’t sure if I was smart enough to trick it into doing my bidding or leverage it like I had Stsadm. I found myself in the first of the seven stages of grief.

After I made it to the seventh stage, Acceptance, I got back up on my horse and starting trying to conquer this beast. I bought a couple of PowerShell books and looked for PowerShell support groups in my area. Nothing seemed to work. I still wasn’t “getting” PowerShell. I still couldn’t do anything with it besides adding two numbers together and writing “Hello World” on my screen. Neither accomplishment would look too impressive on a resume. Maybe I wasn’t smart enough to use PowerShell. Maybe the Wendy’s restaurant down the street could use a new fry cook or Frosty maker.

Lesson 1: Just Use It

One day it finally hit me, I was going at this backward. Instead of learning the language so that someday I could use PowerShell to get tasks done in SharePoint, I should start trying to automate daily SharePoint tasks as a way to help me learn the language. Of all the PowerShell lessons I’ve learned, this one is the most important. That was the day the skies opened up and the sun shone down on me and PowerShell.

Lesson 2: Make Get-Member Your Hero

My first scripts were pretty mundane and basic. It was simple stuff like getting a list of site collections with Get-SPSite or a list of webs with Get-SPWeb. Although they were basic, they did ease me into concepts like PowerShell’s pipeline and how to format command output with cmdlets such as Select-Object and Format-Table. I was able to write handy one-liners like this:

Get-SPSite -Limit all |

  Select-Object Url, Owner, SecondaryContact |

  Format-Table -AutoSize

(Although this command wraps here, you'd enter it all on one line in the PowerShell console. The same holds true for the other commands that wrap.) This one-liner returns a handy list of all the site collections in the farm, along with each site collection’s owner and secondary owner.

In this one-liner, it’s intuitive that the Owner property stores the name of the owner, but the same can’t be said for SecondaryContact property, which stores the name of the secondary owner. An object’s properties and methods aren’t always intuitive, which is one of PowerShell’s little quirks that contribute to its bad reputation and high learning curve. 

Fortunately, PowerShell has the Get-Member cmdlet, which is my hero because it has come to my rescue on many occasions. You can use it with any object to learn about that object’s properties and methods. For example, you can see all the properties of the SPSite object with the following command:

Get-SPSite | Get-Member  

Running this command is how I discovered that I had to use Owner and SecondaryContact to retrieve the names of the primary and secondary owners. It’s also how I discovered countless other gems about all types of objects. Walking through an object’s list of properties and methods has not only made it possible for me to figure out how to accomplish a given task but also inspired me to write scripts for things I didn’t even know was possible.

For example, after getting the members of the SPWeb object, I was inspired to write another handy one-liner. In my SharePoint 2003 and SharePoint 2007 days, I often helped users troubleshoot SharePoint web problems. I’d ask them, “Which template was used to create this web?” They never knew because most of the time they weren’t the people who created that web.

Different webs have different Web Parts and features, so knowing which template was used to create a web is helpful. In SharePoint 2003, there was no way to get that information. In SharePoint 2007, there wasn’t a way before SP2 came out. With PowerShell, it’s easy to discover the template with the command:

Get-SPWeb http://portal.contoso.com/mysteryweb |

  Select-Object Url, WebTemplate, WebTemplateId |

  Format-Table -AutoSize

I would have never thought to use PowerShell for this, but when I used Get-Member with SPWeb I saw the WebTemplate property and my curiosity was piqued. Now I have another invaluable tool in my bag of tricks.

Lesson 3: Take Command with Get-Command

Knowing an object’s members is good, but only after you’ve figured out which objects and cmdlets to use. Learning how to discover cmdlets was another important lesson I learned. It’s done with another of my favorite cmdlets: Get-Command, which lists cmdlets based on the criteria you provide. My first introduction to Get-Command was the following one-liner, which lists all the SharePoint-related cmdlets:

Get-Command -Module Microsoft.Sharepoint.Powershell

There were more than 500, which is too many cmdlets to digest at once. So, I started refining my cmdlet searches with other parameters. For example, the following one-liner gives you all the cmdlets that deal with site collections, or SPSites as PowerShell refers to them:

Get-Command -Noun SPSite

You can substitute any cmdlet verb or noun in that command. You can also use wildcards like this:

Get-Command *SPSite*

A Foundation for the Future

Although I learned these three lessons the hard way, they have allowed me to build an ever-growing foundation of PowerShell understanding. By forcing myself to learn how to do boring everyday tasks in PowerShell, I was gathering the skills needed to write more complicated scripts.

Listing 1 shows one of my latest creations. This script writes SharePoint URLs to a server’s HOSTS file. As a rule, I always point my SharePoint servers at themselves in their HOSTS files. This aids in troubleshooting and helps control which machines the search indexer uses when it performs crawls.

I found myself making the same changes over and over when I performed installations, so this task was a perfect candidate for PowerShell. To write this script, I needed to understand how to get PowerShell to manipulate not only SharePoint but also file systems and the registry. I also needed to be able to walk through a collection of objects with a ForEach loop and manipulate values with the Replace and ToString methods.

Fortunately, I had that foundation, and I was able to write that script with little effort—my favorite kind of writing. You can find more information about this script in my blog post, "PowerShell script to write SharePoint URLs to your server's HOSTS files".

As with any new piece of software, there’s a lot to learn in SharePoint 2010, and learning PowerShell was the most difficult for me. But becoming proficient in PowerShell made me a better SharePoint administrator and probably a better person.

It allows me to automate common SharePoint tasks as well as accomplish some uncommon tasks. On top of that, I can use that same PowerShell knowledge in other products such as Windows Server and SQL Server. I have not only learned PowerShell but also learned to love it.

 

Listing 1: PowerShell Script to Write SharePoint URLs to a Server’s HOSTS File

 

# Make a backup copy of the HOSTS file with today's date.

# Make sure the SharePoint extensions are loaded.

Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0

 

$hostsfile = 'C:\Windows\System32\drivers\etc\hosts'

$date = Get-Date -UFormat "%y%m%d%H%M%S"

$filecopy = $hostsfile + '.' + $date + '.copy'

Copy-Item $hostsfile -Destination $filecopy

 

# Get a list of the Alternate Access Mappings (AAMs) and

# weed out the duplicates.

$hosts = Get-SPAlternateURL | ForEach-Object {$_.incomingurl.replace("https://","").replace("http://","")} |

  Where-Object { $_.tostring() -notlike "*:*" } | Select-Object -Unique

 

# Get the contents of the HOSTS file.

$file = Get-Content $hostsfile

$file = $file | Out-String

 

# Write the AAMs to the HOSTS file, unless they already exist.

$hosts | ForEach-Object { if ($file.contains($_))

{Write-Host "Entry for $_ already exists. Skipping"} else

{Write-host "Adding entry for $_" ; add-content -path $hostsfile -value "127.0.0.1 `t $_ " }}

 

# Disable the loopback check, since everything we just did will fail if it's enabled.

New-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa -Name "DisableLoopbackCheck" -Value "1" -PropertyType dword