PowerShell for Windows Admins

June 18, 2014  1:13 PM

Workflows: 1 Introduction

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

In a recent post I asked for areas of PowerShell that caused problems. Workflows were one of the things mentioned so I’ll start with a series of posts on that topic.

Workflows were introduced to PowerShell in version 3.0 of the Windows Management Framework with Windows 8/2012. A few changes have been made in version 4.0 of WMF (Windows 8.1/2012 R2).

On the surface workflow brings a number of interesting, and potentially very useful, aspects to PowerShell including:

– parallel execution

– ability to survive a reboot of remote or local machine

– ability to checkpoint the workflow and restart at that point

– your task is long running

– your task needs to be run asynchronously

– your task needs to be run on multiple devices

In reality these aims can be met without using workflows. You can use background jobs, multiple instances of a PowerShell script, remoting, scheduled jobs etc to run your tasks. One thing that workflows are good at though is surviving reboots.

Since the flurry of activity that marked their introduction there hasn’t been a lot of noise about workflows. I think that one of the reasons is that they are perceived to be too hard. Workflows look like PowerShell but are subtly different  – they aren’t actually PowerShell even though they use the same syntax. We’ll delve into what they are under the covers in a future post. For now they look like PowerShell and do stuff for us.

Here’s the world’s simplest workflow:

workflow ourfirstworkflow {
“PowerShell rocks”


if you’re looking at that and thinking it looks like a PowerShell function you’d be right. Swap the workflow key word out for function and you get

function ourfirstworkflow {
“PowerShell rocks”


Try running the workflow and the function. The function returns the string almost instantaneously. The workflow needs to build the workflow functions in the background before it can run. Any subsequent runs use the “compiled” (its not a true compile but the term serves for what’s happening) workflow and run just about as quick as the function.

One way to achieve parallelism in a work flow is to use the –parallel option on a foreach loop. This is especially useful for accessing a set of remote computers. For now though we’ll keep it simple

workflow alittlebitofparrallel {
param (

foreach -parallel ($number in $numbers)
“I am number $number”

alittlebitofparrallel -numbers (1..10)

The statement[s] within the foreach loop are run sequentially but the loop is run in parallel for all numbers. Just inputting 1..10 give these results on my machine:

I am number 10
I am number 9
I am number 8
I am number 7
I am number 6
I am number 5
I am number 4
I am number 3
I am number 2
I am number 1

However if you call the workflow with 100 numbers:

alittlebitofparrallel -numbers (1..100)

You will see some evidence of parallelism at work towards the bottom of the results. My test showed this as part of the output

I am number 45
I am number 43
I am number 11
I am number 8
I am number 14
I am number 51
I am number 49
I am number 52
I am number 48
I am number 46
I am number 10
I am number 7
I am number 47

This shows a very important result – the way parallel processing returns results is random-ish. If you need your results back in a predictable manner – parallel execution in a workflow is not what you want to be doing.

I’ll leave it there for now and next time we’ll look at another way to use parallelism and a way to force sequential activities when that is what you really need.

if you want some more workflow related reading try the help files


June 16, 2014  2:51 PM

PowerShell Summit Europe 2014 Agenda

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The agenda for the PowerShell Summit Europe 2014 is available on line.  See the link from http://powershell.org/wp/community-events/summit/

The Summit is a benefit of AWPP membership which will be available from 15 July 2014. We only have room for 60 attendees so please sign up early to avoid disappointment.

June 16, 2014  12:45 PM

Difficult bits of PowerShell?

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell has grown from the original 137 cmdlets to a huge many faceted management platform. Each new iteration of PowerShell sees new features – Remoting, Workflow, DSC, OneGet. I don’t expect that to change in the near future.

The sheer size of PowerShell means its very difficult to be an expert in everything?

Is there anything that you find particularly hard or need more examples?

Please leave a comment if there is something in particular you would like covered.

June 15, 2014  8:33 AM

PowerShell Summit DSC sessions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Steve Murawski gave three exceptional sessions on using DSC at the recent PowerShell summit.

The videos of those sessions can be found here –




Highly recommended

June 13, 2014  7:13 AM

PowerShell Summit Europe 2014 – – update 1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The PowerShell Summit in Europe for 2014 will be held in Amsterdam – 20 September to 1 October

Details are available here – http://eventmgr.azurewebsites.net/home/event/PSEU14

The agenda is shaping up nicely and we’re looking to publish that soon. Shortly after that we will be opening up the registration process. There are a limited number of places available so please keep an eye open for announcements from powershell.org

June 11, 2014  2:18 PM

Rename a user account to the display name

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory Administration

I had a question left on my blog about renaming all of the user accounts in an OU had their name changed to match the display name.  I started by creating a few dummy accounts:

PS s> Get-ADUser -Filter * -SearchBase “OU=Test,DC=Sphinx,DC=org”  -Properties DisplayName | Format-Table DisplayName, Name -AutoSize

DisplayName Name
———– —-
Green Fred  Fred Green
Green Jo    Jo Green
Green Dave  Dave Green

In the case of the first account the goal is to change the Name to match the display name.

One thing to be aware of with AD names – NEVER, NEVER, NEVER and I mean NEVER use a comma between the first and last parts of the name. So

CN=Fred Green,OU=Test,DC=sphinx,DC=org

is good

CN=Green Fred,OU=Test,DC=sphinx,DC=org

is good

CN=Green, Fred,OU=Test,DC=sphinx,DC=org


The reason is that the comma is a delimiter between the parts of the distinguished name. LDAP doesn’t expect a comma between parts of an element so it errors.  You have to escape the comma so its treated as a literal character. I can guarantee that you will forget. Been there, done that & designed the T-Shirt.

Don’t use commas – its fair simpler and you’ll have less errors.

The only option to rename an object is to use Rename-ADObject

PS > Get-ADUser -Filter * -SearchBase “OU=Test,DC=Sphinx,DC=org”  -Properties DisplayName | foreach {Rename-ADObject -Identity $_.DistinguishedName -NewName $_.Displayname -PassThru}

You’ll get a display showing the new names.

If you want to check run the original test

PS > Get-ADUser -Filter * -SearchBase “OU=Test,DC=Sphinx,DC=org”  -Properties DisplayName | Format-Table DisplayName, Name -AutoSize

DisplayName Name
———– —-
Green Fred  Green Fred
Green Jo    Green Jo
Green Dave  Green Dave

Job done

June 10, 2014  12:44 PM

File system ACLS – inheritance

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
NTFS permissions

When you look at a FileSystemAccessRule it’llbe something like this:

FileSystemRights  : Modify, Synchronize
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited       : True
InheritanceFlags  : None
PropagationFlags  : None

So far we haven’t dealt with the three inheritance flags.

Isinherited indicates that the permission is inherited from further up the file system tree

The Inheritance flags –  http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.inheritanceflags(v=vs.110).aspx – are from the System.Security.AccessControl.InheritanceFlags enumeration:


ContainerInherit – child containers (folders) inherit the permission

ObjectInherit – child leaf objects (files) inherit the permission

The popagation flags are from the System.Security.AccessControl.PropagationFlags enumeration – http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags(v=vs.110).aspx

None – no inheritance flags are present

InheritOnly – ACE is propagated to child containers and leaf objects

NoPropagateInherit – specifies the ACE is NOT propagated to child objects

This leads to our function being modified to look like this:

function add-acl {
param (
[ValidateScript({Test-Path -Path $_ })]


[ValidateSet(“Read”, “Write”, “ListDirectory”, “ReadandExecute”, “Modify”, “FullControl”)]
[string]$permission = “Read”,






$fsr = [System.Security.AccessControl.FileSystemRights]::$permission
if ($containerinherit -OR $objectinherit) {
$propflag = [System.Security.AccessControl.PropagationFlags]::InheritOnly
else {
$propflag = [System.Security.AccessControl.PropagationFlags]::None

if ($containerinherit) {

$inhflag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit

if ($objectinherit) {
$inhflag = [System.Security.AccessControl.InheritanceFlags]::ObjectInherit

if ($NOinherit) {
$inhflag = [System.Security.AccessControl.InheritanceFlags]::None

if ($deny) {
$alwdny = [System.Security.AccessControl.AccessControlType]::Deny
else {
$alwdny = [System.Security.AccessControl.AccessControlType]::Allow
$acr = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $trusteeName, $fsr, $inhflag, $propflag, $alwdny

$acl = Get-Acl -Path $path
Set-Acl -Path $path -AclObject $acl -Passthru

Examples of use:

add-acl -path C:\Test -trusteeName “$($env:COMPUTERNAME)\NewUser” -permission FullControl -NOinherit
add-acl -path C:\Test -trusteeName “$($env:COMPUTERNAME)\NewUser” -permission FullControl -containerinherit
add-acl -path C:\Test -trusteeName “$($env:COMPUTERNAME)\NewUser” -permission FullControl -objectinherit

Set the permissions on the folder, the subfolders and the files respectively.

If you want all three – run it three times as above

June 8, 2014  7:32 AM

Function parameter validation – other validation options

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Some other options you can use for validating your input include:


tests the number of values being passed to the parameter – must be within the range (including end points ) specified


test the number of characters in a parameter value – must be within the specified range
[ValidatePattern(“\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b”)] ## IP Address

tests the input value against a regular expression – the value must match the pattern otherwise an error will be thrown


the value must be between the endpoints of the range specified

[ValidateSet(“Low”, “Average”, “High”)]

the value must be a member of the set of values specified

Using these, together with the ValidateScript and Validate  NotNullorEmpty options, provide you an easy way to test and validate your function inputs.  Much easier than writing your own code

June 7, 2014  9:33 AM

DSC Resource Kit wave 4 now available

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The next wave of the DSC resource kit has been released. Notable additions include support for configuring DNS and DHCP servers and your event logs.

Details from http://blogs.msdn.com/b/powershell/rss.aspx

June 6, 2014  7:36 AM

PowerShell Summit NA 2014 sessions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The slides and code from my three sessions

WSMAN cmdlets

Networking administration

Cmdletize the Registry

are available from


You can find videos of some of the sessions – including my three here


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: