Monthly Archive


Monthly Archives: August 2015

Manning Deal of the Day–31 August 2015

Deal of the Day August 31: Half off my book Learn Active Directory Management in a Month of Lunches. Use code dotd083115au at

Learn ConfigMgr 2012 in a Month of Lunches and Learn SQL Server Administration in a Month of Lunches also included

PowerShell User Group meeting in Manchester

The UK PowerShell User Group was the World’s first user group dedicated to PowerShell. Its been in hibernation for the last few years but Ryan Yates is bringing it back to life.


He’s set up a meeting in Manchester for Tuesday 13 October 2016. See

for details.


If you’re in the area I’d recommend you get there if you can

PowerShell Summit Europe 2015 final schedule

The schedule for the PowerShell Summit Europe 2015 has been finalised.  See the event site at

PowerShell gallery security

There are a number of  concerns with pulling code from the Internet e.g. code quality and whether it contains malicious actions.


The PowerShell gallery has implemented a couple of features that should help.


All modules have to meet a minimum quality standard as outlined here -


You can also use Save-Module to download the module to a safe location so you can inspect the contents.

Creating JSON from a hash table

A question on the forum was asking about creating a JSON structure for use with a REST API.

The original has table looked like this

$body = @{
auth_token = "$auth_token"
items = @{
label = "server1"
value = "OK"
label = "server2"
value = "OK"


This fails because you can’t have duplicate keys in a hash table.


One way to create the JSON is like this

$items = @()
$items += @{label = "server1"; value = "OK"}
$items += @{label = "server2"; value = "OK"}

$body = New-Object -TypeName PSOBject -Property @{
auth_token = "$auth_token"
Items = $items

ConvertTo-Json -InputObject $body


which gives:

    "Items":  [
                      "value":  "OK",
                      "label":  "server1"
                      "value":  "OK",
                      "label":  "server2"
    "auth_token":  ""


The items are created by adding hah tables to a pre-existing hash table.  You’re creating a hashtable of hash tables.


If you need to control the order of values you need an ordered hash table to use with New-Object

$items = @()
$items += @{label = "server1"; value = "OK"}
$items += @{label = "server2"; value = "OK"}

$props =  [ordered]@{
auth_token = "$auth_token"
Items = $items

$body = New-Object -TypeName PSOBject -Property $props

ConvertTo-Json -InputObject $body


which gives

    "auth_token":  "",
    "Items":  [
                      "value":  "OK",
                      "label":  "server1"
                      "value":  "OK",
                      "label":  "server2"

Passing data into Jobs

PowerShell jobs are a powerful tool for running processes in the background. You have to remember that a PowerShell job runs in a separate process that only exists for the duration of the job. The results are returned to your process when the job finishes.


A user on the forum asked about passing variables into jobs.  He’d done this:

$w = '1..10'
Invoke-Expression $w

and got the expected result



He then tried this

Start-Job -ScriptBlock { Invoke-Expression $w}

But the job said

Cannot bind argument to parameter 'Command' because it is null.
    + CategoryInfo          : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpre
    + PSComputerName        : localhost


Irrespective of whether using Invoke-Expression is a good idea  and I’ll cover that in a future post the job fails because its failing to find $w because the job is running in a separate PowerShell process and $w doesn’t exist.


The simplest answer is to make the job self contained

Start-Job -ScriptBlock { $w = '1..10'; Invoke-Expression $w}


Everything is in the script block passed to the job and therefore passed to the new PowerShell process.


Alternatively, you can pass the variable $w into the script block

Start-Job -ScriptBlock { param($w) Invoke-Expression $w} -ArgumentList $w


You need to define a param block on the script block and pass the $w variable to it using the –Argumentlist parameter on start-job.


Another option introduced with PowerShell 3.0 us the $using scope modifier

Start-Job -ScriptBlock { Invoke-Expression $using:w}


Which is another way to say use the $w variable from the current scope


You can find out more on $using from about_scopes, about_Remote_Variables

WinOps conference

The WinOps conference will take place 22 September 2015 in London.


Details from


Its all about “Windows in a DevOps world”

Windows 10 and PSScriptAnalyzer

if you were wondering where the PSScriptanalyzer module was in Windows 10 RTM  - its not there.  Its been moved out of core PowerShell and is now available on the PSGallery.

£> Find-Module *Script*

Version    Name                                Repository
-------    ----                                ----------
0.1        nScriptAnalyzerRules                PSGallery
1.0.2      PSScriptAnalyzer                    PSGallery    ScriptBrowser                       PSGallery    ScriptCop                           PSGallery    ScriptCS                            PSGallery
1.0        ScriptTransforms                    PSGallery
1.0        SQLInvokeScripts                    PSGallery


You can install it from the gallery

£> Install-Module -Name PSScriptAnalyzer


You are installing the module(s) from an untrusted repository. If you trust this repository, change its
InstallationPolicy value by running the Set-PSRepository cmdlet.
Are you sure you want to install software from ''?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"): y


By default the gallery isn’t a trusted source so you’ll need to confirm the install.  I’d recommend NOT making PSGallery a trusted source. That designation should be reserved for your internal repositories.


The module has 2 cmdlets

£> Get-Command -Module PSScriptAnalyzer

CommandType     Name
-----------     ----
Cmdlet          Get-ScriptAnalyzerRule
Cmdlet          Invoke-ScriptAnalyzer


You can view the rules currently available:

£> Get-ScriptAnalyzerRule | Format-Table RuleName, Severity -AutoSize

RuleName                                          Severity
--------                                          --------
PSAvoidUsingCmdletAliases                          Warning
PSAvoidDefaultValueSwitchParameter                 Warning
PSAvoidUsingEmptyCatchBlock                        Warning
PSAvoidGlobalVars                                  Warning
PSAvoidInvokingEmptyMembers                        Warning
PSAvoidUsingPositionalParameters                   Warning
PSReservedCmdletChar                               Warning
PSReservedParams                                   Warning
PSAvoidShouldContinueWithoutForce                  Warning
PSAvoidUsingDeprecatedManifestFields               Warning
PSProvideDefaultParameterValue                     Warning
PSAvoidUninitializedVariable                       Warning
PSAvoidUsingUserNameAndPassWordParams                Error
PSAvoidUsingComputerNameHardcoded                    Error
PSAvoidUsingConvertToSecureStringWithPlainText       Error
PSAvoidUsingInternalURLs                       Information
PSAvoidUsingInvokeExpression                       Warning
PSAvoidUsingPlainTextForPassword                   Warning
PSAvoidUsingWMICmdlet                              Warning
PSAvoidUsingWriteHost                              Warning
PSUseOutputTypeCorrectly                       Information
PSMissingModuleManifestField                       Warning
PSPossibleIncorrectComparisonWithNull              Warning
PSProvideCommentHelp                           Information
PSUseApprovedVerbs                                 Warning
PSUseCmdletCorrectly                               Warning
PSUseDeclaredVarsMoreThanAssigments                Warning
PSUsePSCredentialType                              Warning
PSShouldProcess                                    Warning
PSUseShouldProcessForStateChangingFunctions        Warning
PSUseSingularNouns                                 Warning
PSDSCDscTestsPresent                           Information
PSDSCDscExamplesPresent                        Information
PSDSCUseVerboseMessageInDSCResource            Information
PSDSCUseIdenticalMandatoryParametersForDSC           Error
PSDSCUseIdenticalParametersForDSC                    Error
PSDSCStandardDSCFunctionsInResource                  Error
PSDSCReturnCorrectTypesForDSCFunctions         Information


You can also get a description of the rule. Its worth reading through the rules to see what is considered best practice by the authors of this module!

This simple script should trigger a few rules Smile

Write-Host 'getting data'
gwmi Win32_computersystem


£> Invoke-ScriptAnalyzer -Path C:\TestScripts\testsa.ps1 | fl

RuleName : PSAvoidUsingWriteHost
Severity : Warning
Line     : 1
Column   : 1
Message  : File 'testsa.ps1' uses Write-Host. This is not recommended because it may not work in some hosts or there  may even be no hosts at all. Use Write-Output instead.

RuleName : PSAvoidUsingPositionalParameters
Severity : Warning
Line     : 2
Column   : 1
Message  : Cmdlet 'gwmi' has positional parameter. Please use named parameters instead of positional parameters when  calling a command.

RuleName : PSAvoidUsingPositionalParameters
Severity : Warning
Line     : 1
Column   : 1
Message  : Cmdlet 'Write-Host' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

RuleName : PSAvoidUsingCmdletAliases
Severity : Warning
Line     : 2
Column   : 1
Message  : 'gwmi' is an alias of 'Get-WmiObject'. Alias can introduce possible problems and make scripts hard to  maintain. Please consider changing alias to its full content.


Nice simple way to test your code for best practices and avoid some of the major issues that make scripts difficult to read and maintain

Masking output

A question on the forum on how to stop the output from New-Item raises an important point. Many cmdlets produce output when run for example

£> New-Item -Type File -Name test.txt

    Directory: C:\Test2

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       08/08/2015     14:14              0 test.txt


There are times when you want to hide that output. The converse situation where you want output from cmdlets that don’t normally produce it can be resolved with the –Passthru parameter where present or by using –verbose.


You have a number of choices when trying to mask output

£> New-Item -Type File -Name test1.txt | Out-Null
£> [void](New-Item -Type File -Name test2.txt)
£> New-Item -Type File -Name test3.txt > $null
£> $nf = New-Item -Type File -Name test4.txt


Any of the above techniques will work. I prefer the first one as I can develop and test the code showing output and then pipe to out-null to mask it

WMF 5 roadmap

With the recent release of Windows 10 a lot of confusion has arisen regarding the position of PowerShell 5.0.


That confusion has been cleared up with a post from the PowerShell team -