Monthly Archive


PowerShell v4

PowerShell package management on PowerShell 3 and 4

PowerShell 5.0 introduced PackageManagement (Oneget) – for managing software installation packages and PowerShellGet for managing PowerShell modules.


Those features are now available on PowerShell 3 and 4

WMF 4.0 Updates available downlevel

The WMF 4.0 Updates that were released in November 2014 for Windows 8.1 and Windows Server 2012 R2 are now available for:

Windows Server 2012

Windows Server 2008 R2 SP1

Windows 7 SP1


You need WMF 4.0 installed to install the update


Details from

Creating NIC team without knowing the team members

I was asked how to create a NIC team only using the 1GB adapters without knowing how many 1gb NICs were on the server.


I think this should solve the problem


New-NetLbfoTeam -TeamMembers (Get-NetAdapter | where Speed -ge 1gb | select -ExpandProperty Name) -Name MyTeam


Use New-NetLbfoTeam to create the team. The team member names are generated by


Get-NetAdapter | where Speed -ge 1gb | select -ExpandProperty Name


By putting that statement in parentheses as the value for the –TeamMembers parameter the results are used as the value for the parameter.  Shouldn’t matter now how many NICs or what they are called.  You can modify the filter criteria as required.

Creating a DHCP reservation

For my demo at the PowerShell Summit I wanted to use DHCP for the Linux machine but guarantee that it had a specific IP address.  Time to create a DHCP reservation


The DHCP module in Windows Server 2012 and 2012 R2 enables you to create a reservation:

Add-DhcpServerv4Reservation -ScopeId -IPAddress -ClientId 00155D36C906 -Description "LInux machine" -Name "SphinxLX01"


The clientid is the VMs MAC address.


You can view the current reservations:


£> Get-DhcpServerv4Reservation -ScopeId | fl *

IPAddress             :
ScopeId               :
AddressState          : ActiveReservation
ClientId              : 00-15-5d-36-c9-06
Description           : LInux machine
Name                  : SphinxLX01
Type                  : Both


You can view current leases:

£> Get-DhcpServerv4Lease -ScopeId | fl *

IPAddress             :
ScopeId               :
AddressState          : ActiveReservation
ClientId              : 00-15-5d-36-c9-06
ClientType            : Dhcp
Description           : LInux machine
DnsRegistration       : NotApplicable
DnsRR                 : NoRegistration
HostName              : SphinxLX01
LeaseExpiryTime       :
NapCapable            : False
NapStatus             : FullAccess
PolicyName            :
ProbationEnds         :
ServerIP              :


And all from the comfort of your very own PowerShell prompt

Authorising a DHCP server and creating a scope

I recently re-built my test lab and now need to authorise the DHCP server.

You can test the DHCP server:

£> Get-DhcpServerSetting

IsDomainJoined            : True
IsAuthorized              : False
DynamicBootp              : True
RestoreStatus             : False
ConflictDetectionAttempts : 0
NpsUnreachableAction      : Full
NapEnabled                : False
ActivatePolicies          : True

Authorisation is straightforward

Add-DhcpServerInDC -DnsName -IPAddress

If you only have a single NIC in your DHCP server you don’t need to worry about the IP address

£> Get-DhcpServerSetting

IsDomainJoined            : True
IsAuthorized              : True
DynamicBootp              : True
RestoreStatus             : False
ConflictDetectionAttempts : 0
NpsUnreachableAction      : Full
NapEnabled                : False
ActivatePolicies          : True

Create a scope and activate it

Add-DhcpServerv4Scope -ComputerName server02 -Name "Manticore Scope"  -StartRange -EndRange -Description "Scope for Manticore domain" -Type DHCP -State Active -SubnetMask -LeaseDuration (New-TimeSpan -Days 2)

ComputerName is the name of the DHCP server otherwise the parameters are self explanatory

To view all scopes

Get-DhcpServerv4Scope -ComputerName server02

To view specific scope

Get-DhcpServerv4Scope -ComputerName server02 -ScopeId | fl

ScopeId          :
Name             : Manticore Scope
Description      : Scope for Manticore domain
SuperscopeName   :
SubnetMask       :
StartRange       :
EndRange         :
LeaseDuration    : 2.00:00:00
NapProfile       :
NapEnable        : False
Delay(ms)        : 0
State            : Active
Type             : Dhcp
MaxBootpClients  : 4294967295
ActivatePolicies : True

CIM or WMI – – accessing remote machines

I much prefer the CIM cmdlets for accessing remote machines. The WMI cmdlets use DCOM which is firewall unfriendly and can often be unavailable of a server – cue the dreaded RPC server is unavailable error messages.

By contrast the CIM cmdlets use WSMAN.

For one off access to a remote machine use the computername parameter

Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName RSSURFACEPRO2


If you want to access a machine multiple times in the session create a CIM session – analagous to a remoting session


$cs = New-CimSession -ComputerName RSSURFACEPRO2
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $cs


By default a CIM session uses WSMAN

£> $cs

Id           : 1
Name         : CimSession1
InstanceId   : 30c2b530-4ff7-448e-b68d-1f1282890e6a
ComputerName : RSSURFACEPRO2
Protocol     : WSMAN


though you can configure them to use DCOM if need be

$opt = New-CimSessionOption -Protocol DCOM
$csd = New-CimSession -ComputerName RSSURFACEPRO2 -SessionOption $opt
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $csd


When would you need to use DCOM – if you are accessing a machine with PowerShell 2 installed. The CIM cmdlets want to use WSMAN 3 and will error if you access a machine with WSMAN 2 installed however if you include a –Filter they will work


Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName computer1

will fail if computer1 is running WSMAN 2 (PowerShell 2)

However, if you change the command to include a filter

Get-CimInstance -ClassName Win32_OperatingSystem -Filter "Manufacturer LIKE 'Microsoft%'" -ComputerName computer1


Even if, as in this case, the filter doesn’t actually do anything

CIM or WMI – – using methods

The CIM and WMI cmdlets both provide a way to use the methods on CIM classes namely Invoke-CimMethod and Invoke-WmiMethod. The cmdlets are very similar in operation.

$vol = Get-WmiObject -Class Win32_Volume -Filter "DriveLetter = 'D:'"

Invoke-WmiMethod -InputObject $vol -Name Chkdsk -ArgumentList $false, $true, $true, $false, $false, $false


The argumenst list isn’t very informative – unless you know the class, read the documentation or investigate with Get-CimClass


Using the CIM cmdlets is a bit more informative as to what is going on.

$vol = Get-CimInstance -ClassName Win32_Volume -Filter "DriveLetter = 'D:'"

Invoke-CimMethod -InputObject $vol -MethodName Chkdsk -Arguments @{FixErrors=$false; ForceDismount=$false; OkToRunAtB
ootUp = $false; RecoverBadSectors = $false; SkipFolderCycle = $true; VigorousIndexCheck = $true}


You present the arguments as a hash table – this means you can create the hash table and pass it to the method

$margs = @{
OkToRunAtBootUp = $false
RecoverBadSectors = $false
SkipFolderCycle = $true
VigorousIndexCheck = $true
Invoke-CimMethod -InputObject $vol -MethodName Chkdsk -Arguments $margs


This also means that you can create a default set of values and manipulate them in your scripts very easily


Using Invoke-CimMethod involves more typing but I think that’s worth it for the clarity. Of course if you are going to be using the methods of class a lot then I’d recommend that you create a CDXML module from the class – but that’s a whole different set of articles.

Workflows 7: checkpointing workflows

Consider this workflow

workflow chkpt1 {


foreach ($x in 1..20){



It will dump out the process information then output the numbers 1 to 20.  Not a particularly enlightening workflow but it forms  a nice basis for demonstrating checkpoints.

A checkpoint saves the state and data in the workflow. If the workflow is suspended or interrupted the work flow can be restarted from the most recent checkpoint rather than a complete restart from the beginning.


Change the workflow to give a long running activity

workflow chkpt1 {


foreach ($x in 1..1000){


Let the process data be displayed and then stop execution once the numbers start displaying – this is easiest if you use ISE. If you want to restart the workflow you have to start it right from the beginning.

Add a checkpoint to the workflow. This can be achieved in a number of ways.

Use the Checkpoint-Workflow activity to the workflow.

workflow chkpt1 {


foreach ($x in 1..1000){



or use the –PSPersist parameter

workflow chkpt1 {

Get-Process -PSPersist

foreach ($x in 1..1000){



I prefer to use Checkpoint-Workflow as it is more obvious to me when I review the workflow.


if you want to checkpoint your workflows – you have to start them as a job


chkpt1 –AsJob


Then shut down ISE

Open another PowerShell session with elevated privileges. Use Get-Job to see the suspended job.

View the data in the job

Receive-Job -Id 5 –Keep


Restart the job

Resume-Job -Id 5


Once the job finishes view the data and you’ll see the process data and the list of numbers.

Use Checkpoint-Workflow as many time as necessary to protect your data in long running workflows. A checkpoint is a good idea any time that it would be expensive to restart the whole process.

Workflows 6: suspending jobs

One of the great things about work flows is that you can stop and start them. A workflow can be stopped, on a temporary basis, by using the Suspend-Workflow activity.

workflow suspend1 {





This will run the Get-Service activity – and produce output to the console. The workflow will suspend and automatically create a job. You will see output like this:

HasMoreData     : True
StatusMessage   :
Location        : localhost
StartParameters : {}
Command         : suspend1
JobStateInfo    : Suspended
Finished        : System.Threading.ManualResetEvent
InstanceId      : bbe0903d-1720-46da-a6dd-e0a927aa9e11
Id              : 8
Name            : Job8
ChildJobs       : {Job9}
PSBeginTime     : 30/06/2014 19:40:29
PSEndTime       : 30/06/2014 19:40:29
PSJobTypeName   : PSWorkflowJob
Output          : {}
Error           : {}
Progress        : {}
Verbose         : {}
Debug           : {}
Warning         : {}
State           : Suspended


Notice the state.

You can  manage the job with the standard job cmdlets

£> Get-Job

Id Name PSJobTypeName State     HasMoreData Location  Command
-- ---- ------------- -----     ----------- --------  -------
8  Job8 PSWorkflowJob Suspended True        localhost suspend1


The job is restarted using Resume-Job. Once the job has finished you can use Receive-Job to get the rest of the data.

Workflows: 5a CDXML modules update

In my last post I questioned why commands from CDXML didn’t fail as thee weren’t any activities defined for them.  Turns out that functions and other commands that don't explicitly have their own workflow activities are implicitly wrapped in the inline script activity.  As CDXML modules effectively create a function – that means that workflows accept them and run.

Thanks to Steve Murawski for the answer.