PowerShell for Windows Admins

August 19, 2015  10:03 AM

Creating JSON from a hash table

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
JSON, Powershell

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”

August 18, 2015  7:33 AM

Passing data into Jobs

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

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

August 11, 2015  12:45 PM

WinOps conference

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DevOps, Powershell

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

Details from http://winops.org/

Its all about “Windows in a DevOps world”

August 10, 2015  5:51 AM

Windows 10 and PSScriptAnalyzer

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

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 ‘https://www.powershellgallery.com/api/v2/’?
[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.

August 8, 2015  7:19 AM

Masking output

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

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 cjoices 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

August 7, 2015  2:43 AM

WMF 5 roadmap

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

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 – http://blogs.msdn.com/b/powershell/archive/2015/08/06/windows-management-framework-wmf-5-0-roadmap.aspx

August 6, 2015  10:23 AM

KB3081424 failed to install

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

Microsoft rolled out a Cumulative Update for Windows 10 – KB3081424 today. It downloaded and tried to install – got about 30% of the way through, rebooted and then went through a number of reboot cycles to uninstall the changes.

An article here http://news.softpedia.com/news/windows-10-cumulative-update-kb3081424-fails-to-install-stuck-in-reboot-loop-488638.shtml

suggested that deleting keys related to orphaned profiles (users no longer exist) from

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

may fix the problem.  As it happened I had an orphaned profile key, deleted it and retried the install of KB3081424.

It worked

August 5, 2015  1:29 PM

WMF 5.0 COM applications

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
COM, Microsoft Office 2013, Powershell

One change in WMF 5.0 that I hadn’t got round to testing was the speed up in COM based operations.

COM – Component Object Model – was the Microsoft programming model before .NET.  Its old but still around – the interfaces for Internet Explorer and Office are all COM based for instance.

WMF 5.0 promises faster running for COM based applications.  To test it I tried an old script that opens an Excel spread sheet and populates some columns.

$xl = New-Object -comobject ‘Excel.Application’
$xl.visible = $true
$xlbooks =$xl.workbooks
$wkbk = $xlbooks.Add()
$sheet = $wkbk.WorkSheets.Item(1)

## create headers
$sheet.Cells.Item(1,1).FormulaLocal = ‘Value’
$sheet.Cells.Item(1,2).FormulaLocal = ‘Square’
$sheet.Cells.Item(1,3).FormulaLocal = ‘Cube’
$sheet.Cells.Item(1,4).FormulaLocal = ‘Delta’

$row = 2

for ($i=1;$i -lt 25; $i++){

$f = $i*$i

$sheet.Cells.Item($row,1).FormulaLocal = $i
$sheet.Cells.Item($row,2).FormulaLocal = $f
$sheet.Cells.Item($row,3).FormulaLocal = $f*$i
$sheet.Cells.Item($row,4).FormulaR1C1Local = ‘=RC[-1]-RC[-2]’


In the past working with Excel has been glacially slow. So slow that you could watch each individual change.

In WMF 5.0 its much, much faster.

In the past my advice has been to create a CSV file and then import the data from that into Excel. With the much better speed offered by WMF 5.0 I may have to reconsider that and think that working directly with Excel is now a viable proposition.

August 3, 2015  1:29 PM

Windows 10 licensing

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

The way Windows updates are going to be delivered is changing – you should read this – http://blogs.technet.com/b/uktechnet/archive/2015/07/13/windows-10-licensing-logic.aspx – to understand what it means for you and your organization

August 3, 2015  10:46 AM

PowerShell Summit NA 2016 – Call for Topics

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The PowerShell Summit is the number one conference where PowerShell enthusiasts gather and learn from each other in fast-paced, knowledge packed presentations. PowerShell experts from all over the world including MVP’s, Guru’s, community leaders and PowerShell team members, will once again join together for a few days in Bellevue, WA. to discuss and learn about maximizing PowerShell in the workplace. If you want to share your PowerShell expertise or story, then this is your official call to submit presentations for selection!

PowerShell Summit North America 2016 will be held 4-6 April in the Meydenbauer center, Bellevue WA.

Topic Areas – What we are looking for

We are looking for 45-minute presentations covering a wide aspect of PowerShell expertise. We have two main topic areas that may assist you in building an abstract.

PowerShell Internals – A deep look into the inside workings of PowerShell and practical solutions that are built from them. These presentations are typically more directed to the PowerShell development community that is building extensions and solutions relating to PowerShell.

PowerShell Features Deep Dive – These presentations are a deep look into configuring and working with PowerShell features and capabilities such as Remoting, Desired State Configuration and more. These presentations tend to be more IT Pro focused.

We are open to presentations across the entire ecosystem that has been built around PowerShell; so don’t hesitate to send an abstract for your particular area of expertise. This includes Microsoft platforms and products that have PowerShell-based management tools as well as 3rd parties such as VMware. New topics will be preferred over recycling of older topics – look to see what’s new in PowerShell 5.0 and use the questions on PowerShell.org to spot areas of confusion that could supply a good session for the Summit.

We may consider double length sessions, but only in exceptional cases. Please contact us – summit@powershell.org – with your idea before spending too much time developing such a session.

 What kind of sessions get selected?

We’re looking for sessions that go beyond – way beyond – “beginner.” If you want to see examples of the depth we’re looking for use the recordings on the PowerShell.org Youtube channel from the PowerShell Summit Europe 2014, or PowerShell Summit NA 2015 as a guide. We look for an abstract that’s compelling and makes us salivate to see your session – so spend time writing a punchy abstract! We want sessions that offer real-world usability combined with “wow, nobody talks about THAT” awesomeness. If in doubt aim high, very high. Remember, Summit sessions are recorded, so if you’ve previously presented a topic at a Summit, we’re less likely to choose it for another Summit. We want sessions that are challenging, and that ideally present things that simply aren’t explained or documented elsewhere. New modules, new techniques, and crazy approaches are all welcome. Discussion-format sessions are great, too, especially if you plan to turn them into a community deliverable (like a “best practices for writing DSC Resources” session that gets turned into a free e-guide later). Think community, deep dive, engaging, and amazing as keywords. We want attendees to finish each day with information leaking… just a little bit… out their eyeballs. Help us make it happen.

If you have any doubts about the suitability of a particular session please contact us – summit@powershell.org – we’re always happy to discuss proposed sessions.

We do have some goals for speaker selection, too. We obviously have, and appreciate, the great involvement we get from the product team. We aim to have a certain number of sessions from well-known members of the community, simply because they’re well-known for a reason – they do a great job! But we also set aside slots for newcomers who’ve never presented before, or who’ve maybe only presented once or twice before – the audience will judge you on content not style. We want to create opportunities for more folks to become engaged and active in our community, and the Summit is a great way to do that.

We aren’t looking for soft-skills sessions, like “how to get a new user group running,” although contact us via email (summit@powershell.org) if you’d like to do something like that as an extra evening thing after the main content wraps for the day.

Please note all sessions are to be delivered in English. Presenter will provide all equipment needed to deliver session(s), including a laptop or other computer. Presenter must be able to provide video by means of HDMI, DVI-D, or DisplayPort connectors – VGA is NOT supported. Presenter must be able to manually select an appropriate screen resolution for video output. Typically, 1024×768 or 1280×720 are preferred.

How to submit abstracts of presentations

Presentations will be 45-minutes in length and the submission should include the following:

Presentation Title

Presentation abstract – a description of the presentation and the topics covered. 250 words or less and suitable for marketing.

Go to https://eventloom.com/event/register/PSNA16/Speaker?preregister=1.

This is the only valid URL for pre-registration. Provide your e-mail address, password, and confirm password. You’re creating a new account, even if you’ve attended past Summit events.


Click Abstracts on the top menu


Enter Title and Description.


Provide a title and description; descriptions must be 50-250 words. Set the Status to “Ready to Review” when you are ready to send your session to us for consideration.

To return to the site at a later time, go to https://eventloom.com/event/login/PSNA16

Click Log In. You can then re-visit Abstracts.

Note that you must set your abstract status to Ready for Review or we won’t see it. If you leave it in Pending, it won’t be considered.

You can submit multiple presentations in the same topic area or for different ones. Be aware that even though the session length is 45 minutes we prefer to have at least 10 minutes set aside for questions. Summit presentations are intense and intimate often with plenty of audience interaction. You must expect questions and discussions. This is not a “lecture to the audience” event. Also because of the session length, generally co-presenters are unnecessary, but that is not a requirement.

Presentation submission deadline – When you should send it by

Start sending your presentation submissions immediately! The selection committee will start selecting presentations as soon as they arrive so you don’t want to miss out. The last day we will accept presentation submissions will be Thursday 1 October 2015. This is a hard deadline – no sessions will be accepted after this date.

When you will know you’ve been selected

The selection committee will start reviewing submissions immediately and begin the selection process. You will be informed if one or more of your presentations have been selected and notified by Thursday 15 October 2015.

You will need to log back onto the event site and complete your registration with the code we will provide in the notification email. This will have to occur before 31 October 2015 so that we have a completed agenda in time for attendee registration.

Speakers, with accepted sessions, will be given free admission to the event, including attendance at all official Summit activities. However, AWPP membership is not included. Speakers may not bring guests to the day sessions or evening events. We have a limited budget, and the number of speakers selected will be partially governed by that budget.

Pre-registering does not guarantee you a place at the event. Pre-registration is until 1 October 2015. Final session selections will be made by 15 October 2015, and you will be notified of accepted/unaccepted sessions.

If at least two sessions are accepted, you will be asked to immediately make a reservation at our speaker hotel. You will be given our group code, and we will directly pay for up to 3 nights’ lodging. Any additional nights are your responsibility as are travel and other costs.
If any sessions are accepted, you will be asked to immediately complete your Summit registration using a free promotional code. If you do not complete your registration by 1 November 2015, then we will assume you do not wish to present and your sessions will be cancelled, and the slots offered to another speaker.
If no sessions are accepted, then your pre-registration will be deleted. Beginning 1 November 2015 and through 4 March 2016, you are welcome to create a new account and register as a standard attendee on a space-available basis.
The final agenda will be announced and posted on PowerShell.Org on, or about, Sunday 1 November 2015.

We look forward to your submissions and your help in making PowerShell Summit North America 2016 the most valuable IT/Dev conference of the year building on and surpassing the previous Summits!

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: