1. Introduction to PowerShell
PowerShell to the Rescue!
Since my early days working in MS-DOS, I have enjoyed the tricks of shell-programming or shell-scripting. Being able to tell a machine to do a set of sequential actions in one go, often repetitive tasks, can be a life saver, and sometimes, a way to do something that other APIs won’t allow.
PowerShell to the Rescue
This post will focus on PowerShell, specially oriented for the SharePoint ecosystem.
2. The basics
PowerShell is “a task automation and configuration management framework from Microsoft, consisting of a command-line shell and associated scripting language built on the .NET Framework.” [ref]
This means that if you have an assembly of your own, you can easily reference it and use it on your scripts, while taking advantage of all the shell command-lets, such as listing directories, reading/writing csv files, sending emails, and much, much more.
PowerShell has a nice Verb-Noun convention, where some of the verbs are “Get”, “New”, “Set”, “Remove” and some of the interesting nouns, or actions, are “Csv”, “Path”, “Command”.
For example, if you want to know which commands involve working with csv files, you can use Get-Command:
Get-Command –noun csv or Get-Command –noun csv*
To know everything about a command you have already identified, use Get-Help:
Get-Help ConvertTo-Csv –full | more
Mastering piping, wildcards, comparisons and loops will help a lot in the long run.
For example, the one-liner script below will display all text files that contain the word “refactor”:
get-childitem * -recurse -filter *.txt | Select-String -pattern “refactor” | group path | select name | format-list
3. Special tricks
After you have been writing PowerShell for a while, there are a few tasks and conventions that you start following, in order to overcome some small caveats.
• Re-starting the shell to add elevation
Sometimes you just want to make sure that your scripts run elevated, and you don’t want to right click and “Run as Administrator”, which may not even be available. This code will make sure you can double-click or “Run with PowerShell” and if the shell is not elevated, it will start an elevated shell and terminate the current instance.
function Ensure-Admin($invocation)
{
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] “Administrator”))
{
$arguments = “& ‘” + $invocation.mycommand.definition + “‘”
Start-Process powershell -Verb runAs -ArgumentList $arguments
throw “running an elevated window!”
}
}
Usage: Ensure-Admin $MyInvocation
• Catching a non-terminating exception
If anything goes wrong with the retrieval of a SPWeb or SPSite object, the script will crash, even if you have a try/catch block. This is because some exceptions are “non-terminating” exceptions. In the script below, you can see how to make Get-SPWeb behave like a terminating exception, should it fail to retrieve the website, and also, how to catch the exact exception, so you can catch other exceptions, if need be.
try
{
$web = get-spweb “http://myweb” -erroraction stop
}
catch [System.Management.Automation.ActionPreferenceStopException]
{
#do stuff
}
Catch
{
#uncaught exception
}
• Ask for user confirmation before doing something
The function below can be called simply to get a yes/no from the user, using built-in objects.
function Get-YesNoAnswer($title, $message)
{
$yes = New-Object System.Management.Automation.Host.ChoiceDescription “&Yes”, `
“confirms action”
$no = New-Object System.Management.Automation.Host.ChoiceDescription “&No”, `
“cancels action”
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $message, $options, 1)
switch ($result)
{
0 {return $true}
1 {return $false}
}
}
Usage:
$answer = Get-YesNoAnswer “WARNING” “Are you sure you want to delete this file?”
• Send a file to recycle bin without prompt
Whenever I can, I tend to “recycle” data instead of using “delete”. If anything goes south, there is always the chance to recover the information. This is valid in SharePoint, as well as in the local machine.
function Delete-ToRecycleBin ($path)
{
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile(((gi $path).FullName), ‘OnlyErrorDialogs’, ‘SendToRecycleBin’)
}
Usage: Delete-ToRecycleBin”testsfile002.txt”
4. Finding the right types for each scenario
While working with documents, often there is a chance to send integers or strings as parameters. Although this brings flexibility to PowerShell, it can make the script harder to understand. Here are a few common operators and methods, especially for document approval.
Client |
Server |
|
Check In |
File.CheckIn(“comment”, [Microsoft.SharePoint.Client. CheckInType]::MajorCheckIn) |
SPFile.CheckIn(“comment”, [Microsoft.SharePoint.SPCheckinType]::MajorCheckIn) |
Check Out |
File.CheckOut() |
SPFile.CheckOut() |
Undo Check Out |
File.UndoCheckOut() |
SPFile.UndoCheckOut() |
Approve (List.EnableModeration) |
Item.[“_ModerationStatus”] = 0 |
SPFile.Approve(“comment”) |
Publish (!List.EnableModeration) |
File.Publish(“comments”) |
SPFile.Publish(“comments”) |
Check Out Type |
[Microsoft.SharePoint.Client.CheckOutType]::None [Microsoft.SharePoint.Client.CheckOutType]::Online [Microsoft.SharePoint.Client.CheckOutType]::Offline |
[Microsoft.SharePoint.SPFile+SPCheckOutType]::None [Microsoft.SharePoint.SPFile+SPCheckOutType]::Online [Microsoft.SharePoint.SPFile+SPCheckOutType]::Offline |
CheckInType |
[Microsoft.SharePoint.Client.CheckInType]::MajorCheckIn [Microsoft.SharePoint.Client.CheckInType]::MinorCheckIn [Microsoft.SharePoint.Client.CheckInType]::OverwriteCheckIn |
[Microsoft.SharePoint.SPCheckinType]::MajorCheckIn [Microsoft.SharePoint.SPCheckinType]::MinorCheckIn [Microsoft.SharePoint.SPCheckinType]::OverwriteCheckIn |
Moderation Status |
0 – approved 1 – denied 2 – pending 3 – draft 4 – scheduled |
[Microsoft.SharePoint.SPModerationStatusType]::Approved [Microsoft.SharePoint.SPModerationStatusType]::Denied [Microsoft.SharePoint.SPModerationStatusType]::Pending [Microsoft.SharePoint.SPModerationStatusType]::Draft [Microsoft.SharePoint.SPModerationStatusType]::Scheduled |
Folder |
[Microsoft.SharePoint.Client.FileSystemObjectType]::Folder |
[Microsoft.SharePoint.SPFileSystemObjectType]::Folder |
Combine Url |
– |
[Microsoft.SharePoint.Utilities.SPUrlUtility]::CombineUrl |
5. Content deployment
• Title
o The good thing about scripting is that we can give a nice title, with spacing and other characters, without harming the URL with characters such as “%20”
• Description
o We can add a meaningful description
• URL
o We can setup a friendly URL, preferably without spaces
• EnableVersioning
o By default, versioning is disabled so we should set it up if it is relevant
• EnableFolderCreation
o By default, creation of folders is enabled, which may not be the intended behaviour
• DefaultItemOpen
o By default, documents will open on the browser, and you may want that they open in the client application
Browser
PreferClient
Miscellaneous tips
• PowerShell is typically used on the Microsoft ecosystem, such as Windows Server. But it can be added to other editions of Windows if it is not shipped by default
• PowerShell is case-insensitive. E.g. get-help produces the same output as Get-Help
• We can load assemblies using Add-Type or [reflection.assembly]::LoadFrom, Load, LoadFile, LoadWithPartialName. Conditions apply when using one or the other
• We can send emails with Send-MailMessage
• We can use Get-Location or its alias “pwd” to get the current path
• Initially, new environments may be unable to run unsigned scripts. To work around this, we can run the cmdlet “set-executionpolicy remotesigned”
• We can include external scripts using “. .common-functions.ps1”
• To customize the screen output, we can use cmdlets such as “clear-host”, “write-host” and “read-host”, and we can also change output colours
• We can use try-catch-finally to handle exceptions, or leverage the usage of “trap”
• We can operators such as –le, -ge, -lt, -gt, -eq, -like, -match, -cmatch, -replace, -contains, etc. [ref]
• We can use the full potential of .Net regular expressions. There is an amazing article from PowerShell.com [ref]
• We can use Start-Transcript and Stop-Transcript to record the output of the session to a file
• Use [guid]::NewGuid() to get a newly generated 128-bit identifier
Sources/further reading
Windows PowerShell, Wikipedia,
http://en.wikipedia.org/wiki/Windows_PowerShell
Text and regular expressions, PowerShell.com,
http://powershell.com/cs/blogs/ebook/archive/2009/03/30/chapter-13-text-and-regular-expressions.aspx
Comparison Operators, TechNet,
https://technet.microsoft.com/en-us/library/hh847759.aspx
Web and library properties,
http://get-spscripts.com/2010/10/changing-sharepoint-list-settings-using.html
http://get-spscripts.com/2010/10/change-sharepoint-list-settings-using.html
http://get-spscripts.com/2011/04/managing-quick-launch-current.html
MVA course, “Getting Started with PowerShell 3.0 Jump Start”,
https://www.microsoftvirtualacademy.com/en-US/training-courses/getting-started-with-powershell-3-0-jump-start-8276
Browse through hundreds of scripts and register for PowerTips, PowerShell.com,
http://powershell.com/cs/blogs/tips/default.aspx
Download PowerGUI PowerShell Script Editor,
http://en.community.dell.com/techcenter/powergui/m/bits
About the Author: Tiago Duarte is a Software Engineer from Portugal. He is actively involved in community forums, events, andtechnical blogs (having one of his own). His field is mostly but not limited to Microsoft Technologies, specially SharePoint Branding and Development. After developing themes for SharePoint whilst on Bind, he is now an independent consultant, working for the European Centre for Disease Prevention and Control (ECDC). He is a certified MCPD and MCITP, and has been speaker, article writer, or otherwise attendant on technology events in Portugal and Sweden. He also has a few side-projects were he develops his own ideas.
Blog: http://ftduarte.blogspot.com
Twitter: https://twitter.com/tduarte85
Website: http://about.me/tiagoduarte