Monthly Archive


Monthly Archives: February 2015

PowerShell Europe 2015 Agenda

As has been announced registration for the PowerShell Summit Europe 2015 opens on 27 February 2015.


Other details on the Summit can be found here:


The agenda for the Summit can be found on the event site for the Summit

Change to DSC Resource Kit release strategy

The PowerShell team blog details the new resources and bug fixes in wave 10 of the DSC resource kit. This is a much smaller release than the of late but includes new resources for initializing and formatting disks




One point in the “small print” is important to note. This is the last release of these resource as a big zip file for download from the TechNet script gallery. In future these resources will only be available through the PowerShell gallery. Use Find-DscResource to discover the resources available in the gallery and Update-Module & Install-module to get the modules containing resources from the gallery.

DSC Resource Kit Wave 10

The next release (wave 10) of the Desired State Resource Kit is available. You can download the whole of the resource kit from

This version includes the IIS resources that were missing in wave 9

WMF 5.0 February 2015 preview

A new preview of Windows Management Framework 5.0 (PowerShell) is available.



for details.


The release notes indicate which new features are considered stable and which are still regarded as experimental and therefore subject to change.


Downloads are available for Windows 8.1 (x32 and x64), Windows Server 2012 R2  Windows 2012. You will need .NET 4.5 installed.

Copy a file with WMI

A question came up on the forum about copying files with CIM (WMI). I normally use Copy-Item rather than CIM as its easier. The questioner was using CIM_LogicalFile when I’ve normally used CIM_DataFile so I decided to take a look at the class. In reality the two classes are very similar and CIM-datafile could be substituted for CIM_LogicalFile in the code that follows.


The obvious starting point is to use the Copy method on the CIM_LogicalFile class


$files = Get-WmiObject -Class CIM_LogicalFile -Filter "Path = '\\Test\\' AND Extension = 'txt'"

foreach ($file in $files) {
$newfile = "C:\Test2\$($file.FileName).$($file.Extension)"



Couple of points to note. In the Path part of the filter you have to escape the \ delimiter.  Extension doesn’t include the ‘.’

You have to give the full path – including file name - to the loaction to which you want to copy the file. In this case you don’t have to escape the \ delimiter. Consistency is a wonderful thing and usually absent from WMI.


You can also use Invoke-WmiMethod


$files = Get-WmiObject -Class CIM_LogicalFile -Filter "Path = '\\Test\\' AND Extension = 'txt'"

foreach ($file in $files) {
$newfile = "C:\Test2\$($file.FileName).$($file.Extension)"
Invoke-WmiMethod -InputObject $file  -Name Copy -ArgumentList $newfile




use the new CIM cmdlets


$files = Get-CimInstance -ClassName CIM_LogicalFile -Filter "Path = '\\Test\\' AND Extension = 'txt'"

foreach ($file in $files) {
$newfile = "C:\Test2\$($file.FileName).$($file.Extension)"
Invoke-CimMethod -InputObject $file  -MethodName Copy -Arguments @{Filename = $newfile}



In this case you have to give the argument name for the method as well as its value. You can discover the method parameters using Get-CimClass


$class = Get-CimClass CIM_LogicalFile

£> $class.CimClassMethods["Copy"].Parameters

Shutting down machines in parallel

My test lab is a set of virtual machines running on a Lenovo w1510 laptop. When I’ve finished working for the day I want to shut down the virtual machines and the laptop. I may have anywhere between 2 and 8 (or more) VMs running so scripting the shutdown helps a lot.


Machines can be shutdown independently so this is an action that is ideal for parallel execution through a workflow.


workflow stop-allvms {
$vms = Get-VM | where State -eq "Running" 
foreach -parallel ($vm in $vms) {
Stop-Computer -PSComputerName $vm.Name -Force -Verbose



Get the running VMs. use foreach –parallel to run stop-computer against each VM. Notice I’ve had to change the parameter on Stop-Computer from –ComputerName to –PSComputerName


Another little workflow that makes life easier. I looks like workflows aren’t going to be the game changer that we originally thought but they do add some interesting options.

Testing AD replication

I thought that using a workflow with its foreach –parallel construct would be a good way to test AD replication.


I found that I got double the results – the foreach seemed to go to each machine twice.


Eventually decided to perform the task sequentially

Get-ADDomainController -Filter * |
foreach {
  Get-ADReplicationUpToDatenessVectorTable -Target $($psitem.Hostname) -Partition * |
  select Server, LastReplicationSuccess, Partition,
  @{N='Partner'; E={(($_.Partner -split ",")[1]).Remove(0,3)}}, USnFilter
} | ft –a


There are a number of cmdlets for working with AD replication that are worth investigating

Typing variables

I was recently asked a question about typing variables after thinking about it came up with this demonstration.

Create a variable with an integer value

£> $a = 2
£> $a.GetType()

IsPublic IsSerial Name
-------- -------- ----
True     True     Int32


AS you would expect – you get an integer type.

If you do this

£> $a = '123'
£> $a.GetType()

IsPublic IsSerial Name
-------- -------- ----
True     True     String


It changes to a string. Which means you can also do this.

£> $a = 'gdyegf'
£> $a.GetType()

IsPublic IsSerial Name
-------- -------- ----
True     True     String


PowerShell variables will adapt their type to the data they contain.

However if you type the variable:

£> [int32]$b = 2
£> $b.GetType()

IsPublic IsSerial Name
-------- -------- ----
True     True     Int32


You start with an integer as expected


If you use a string that can be converted to an integer – that will happen and your type is still an integer.
£> $b = '123'
£> $b
£> $b.GetType()

IsPublic IsSerial Name
-------- -------- ----
True     True     Int32


If you try to put a string in the variable

£> $b = 'effAG'
Cannot convert value "effAG" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:1
+ $b = 'effAG'
+ ~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException


It fails because you can’t convert  'effAG' to an integer.

Untyped PowerShell variables can change their type. If you want to ensure the variable always contains a specific type then force that by typing the variable.

Modifying AD attribute – PO Box

I was left a question on this post -

Asking how to modify the PO Box value for a user account. 


This attribute can be set on the Address tab of AD Users and Computers but isn’t directly visible through AD Administrative Center.


The first trick is to discover the real name of the attribute. One method is to use the Attribute Editor tab in the GUI tools or you can do this:

£> Get-ADUser -Identity richard -Properties * | select *box*



This is where life gets interesting because the actual name of the attribute is postOfficeBox.


Still to set the value

£> Get-ADUser -Identity fgreen -Properties * | select Name, POBox

Name                                                        POBox
----                                                        -----
Fred Green

£> Get-ADUser -Identity fgreen -Properties * | Set-ADUser -POBox 'MX234'
£> Get-ADUser -Identity fgreen -Properties * | select Name, POBox

Name                                                        POBox
----                                                        -----
Fred Green                                                  MX234


Set-ADuser has a parameter specifically for that attibute


If you need to set the PO Box as part of a bulk change follow the style given in the post at the top of this article and add the –POBox parameter to Set-ADuser

Starting VMs based on WSUS state

I use WSUS in my lab to update machines – means I only have to download updates once. The issue is that I have to start the VMs so they can communicate with the WSUS server. WSUS will start to flag warnings if machines haven’t contacted the WSUS server for more than that length of time.


Putting that together I can use the UpdateServices (WSUS) module and the Hyper-V module to start machines that have been turn off more than 7 days.


$date = (Get-Date).AddDays(-7)
Get-WsusComputer -NameIncludes 'W12R2' |
where LastReportedStatusTime -lt $date |
foreach {
  $name = ($psitem.FullDomainName -split "\.")[0]

  $vm = Get-VM -Name $name -ComputerName server02
  if ($vm.State -eq 'Off') {

    Start-VM -Name $name -ComputerName server02
    Start-Sleep -Seconds 30


Set a date 7 days in the past.


Use get-WsusComputer to pull the machine names. I filter on W12R2 (all my machine names contain an abbreviated OS type) and check the last status report time.


Any machines that haven’t reported – the VM data is retrieved and if the machine isn’t running it’s started. Machines take about 25-30 seconds to boot on my lab so a sleep of 30 seconds means I’m not starting them all at once.