Tag Archives: powershell

PowerShell Quick Tip: Testing JSON Syntax

I’ve been working a lot with JSON files recently and quite regularly I need to update their content for testing of code changes. While editing the files I want to make sure I don’t introduce an error by making a syntax error in the JSON file. I’ve been using a quick way in PowerShell to test the JSON is clean and if not, to point me at the line in the file where there is a problem.

Take the following example JSON:

{"people": [
"name": "John Smith",
"city": "London",
"country": "United Kingdom",
"age": 27
"name": "George Burns",
"city": "New York",
"country": "USA",
"age": 32
] }

I can check this in PowerShell by creating a Here-String of the JSON, then using the ConvertFrom-JSON cmdlet.

$text = @"
{"people": [
"name": "John Smith",
"city": "London",
"country": "United Kingdom",
"age": 27
"name": "George Burns",
"city": "New York",
"country": "USA",
"age": 32
] }

$json = $text | ConvertFrom-Json

If there are no issues then I get no errors back and additionally can examine the $json variable to check the contents:



However, if there is a syntax error in the JSON text then I will get something like this:


This line:

ConvertFrom-Json : Invalid object passed in, ‘:’ or ‘}’ expected. (88): {“people”: [

gives us a number, 88, of the character in the string where there is a problem. To head straight to the problem area use:


This will show us text after the error:


and if we look at the text I gave I missed out a ” at the end of “city”: “London, 

{"people": [
"name": "John Smith",
"city": "London,
"country": "United Kingdom",
"age": 27
"name": "George Burns",
"city": "New York",
"country": "USA",
"age": 32
] }


Onyx for the vSphere Web Client

The original Project Onyx (also here) was a VMware Fling which intercepted calls between the C# vSphere client and vCenter and could translate things you did in the GUI client to code in your choice of languages; SOAP, C#, PowerCLI, and JavaScript. This was really useful if say a thing you needed to do was not yet covered by a PowerCLI cmdlet, or you wanted to try and make it faster by using Get-View, or you didn’t know how to code it in JavaScript for vRO.

An issue arose however with the release of the vSphere Web Client, since Project Onyx did not support that method of intercepting calls. When VMware started moving new functionality only into the Web Client, that meant you could not use Project Onyx to figure out the code for those new features.

Enter a new VMware Fling – Onyx for the vSphere Web Client!

Some smart guys have now brought this same functionality to the vSphere Web Client. Let’s take a look at an example of how it works.

First of all follow the instructions on the Fling site to get it installed. Currently it supports vCenter 6.0. Note the warning about only using this Fling in your test environment (that’s where you write and test all of your code anyway right? 😉 )
WARNING: This fling replaces core Web Client files and may cause issues with stability and
patching of future versions of the web client, please only continue with this installation if you are
using a test or dev environment.

Once installed and the vSphere Web Client service has restarted, you will see a new menu item for Onyx.


Currently there is only PowerCLI.NET available as a code output choice. I’m hoping that since it is a drop down menu, there are more to come. I’ve already put in a Feature Request for JavaScript for handy use with vRO 😉


You can either Start and Stop recording from this area or very handily they have added the same buttons in the top right hand corner so that you can Start and Stop recording from anywhere in the Web Client.


So start the recording and navigate to the thing that you want to do. For this example we’ll turn on HA for a cluster.


Once complete, stop the recording.


Now head back to the Onyx section of the Web Client and observe the code required to make that change.


$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
$spec.dasConfig.vmComponentProtecting = 'disabled'
$spec.dasConfig.enabled = $true
$spec.dasConfig.admissionControlEnabled = $true
$spec.dasConfig.vmMonitoring = 'vmMonitoringDisabled'
$spec.dasConfig.hostMonitoring = 'enabled'
$spec.dasConfig.HBDatastoreCandidatePolicy = 'allFeasibleDsWithUserPreference'
$spec.dasConfig.admissionControlPolicy = New-Object VMware.Vim.ClusterFailoverLevelAdmissionControlPolicy
$spec.dasConfig.admissionControlPolicy.failoverLevel = 1
$spec.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings
$spec.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings
$spec.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = 'none'
$spec.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true
$spec.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled'
$spec.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = 180
$spec.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = 'disabled'
$spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings = New-Object VMware.Vim.ClusterVmToolsMonitoringSettings
$spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.failureInterval = 30
$spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailures = 3
$spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow = 3600
$spec.dasConfig.defaultVmSettings.vmToolsMonitoringSettings.minUpTime = 120
$spec.dasConfig.defaultVmSettings.restartPriority = 'medium'
$spec.dasConfig.defaultVmSettings.isolationResponse = 'none'
$spec.dasConfig.option = New-Object VMware.Vim.OptionValue[] (0)
$spec.dasConfig.heartbeatDatastore = New-Object VMware.Vim.ManagedObjectReference[] (0)
$spec.dasConfig.hBDatastoreCandidatePolicy = 'allFeasibleDsWithUserPreference'
$modify = $true
$_this = Get-View -Id 'ClusterComputeResource-domain-c22'
$_this.ReconfigureComputeResource_Task($spec, $modify)

This is super cool. I really like the way it’s been implemented and looking forward to further development of this Fling :-)


PowerShell Module for the Brickset API

Brickset.com is one of my favourite sites for finding info about Lego sets and keeping up-to-date with Lego news. I noticed recently that they had an API so I thought I would check it out. I posted a while back on how to do some similar stuff with other websites, but some of the functionality on those websites is no longer available.

This module for Brickset data contains functions for finding information about Lego sets and also makes it possible to download instruction manuals which can be pretty helpful if you have lost one of them or buy a 2nd hand set without the manuals.

1) Installation

Download the module from Github, ensure the files are unblocked and copy it to one of your PowerShell module folder paths. For me that is C:\Users\jmedd\Documents\WindowsPowerShell\Modules .


If you’ve done it successfully then you should be able to see details of the module with Get-Module:

Get-Module Brickset -Listavailable


You can take a look at the commands available by importing the module and then using Get-Command:

Import-Module Brickset

Get-Command -Module Brickset



2) Get a Brickset API Key

To use the Brickset API you need to first of all register for an API key. Fill out the form here and they will send you one. Currently they are free.

All of the Get-* functions in the module require you to use the API key; you won’t get very far without one.

3) Set a Global Variable for the API Key

Each of the Get-* functions has an APIKey parameter. However, to make things easier to use I’ve also added the Set-BricksetAPIKey function which will create a global variable for the API key that will be valid for the duration of that PowerShell session. If you don’t supply an API key to the Get-* functions then they will look for the global key having been set.

So the best thing to do is run this function first, with your API key, to set the API key variable:

Set-BricksetAPIKey -APIKey 'ed4w-KQA2-1Ps2' -Confirm:$false



4) Getting All Lego Sets by Theme

First example of using one of the Get-* functions is Get-BricksetTheme and Get-BricksetSet. Together they can be used to retrieve a list of Brickset Themes and then the sets in a theme. So let’s take a look at the example:

First of all, use Get-BricksetTheme to retrieve all available Themes from the Brickset site (remember you don’t need to specify the API key if it has already been set:

Get-BricksetTheme | Format-Table Theme,SetCount -AutoSize


Now say we want to retrieve all of the sets for the Indiana Jones theme we can use Get-BricksetSet with the Theme parameter:

Tip: You can use the OrderBy parameter to sort by a particular value. This may be more efficient than piping it through to Sort-Object afterwards:

Note: there is a lot more information available for each set than displayed here. I’ve restricted the output to a few key properties.

Get-BricksetSet -Theme 'Indiana Jones' -OrderBy Pieces | Format-Table Name,Number,Theme,SubTheme,Year,Pieces -AutoSize


5) Getting All Lego Sets by Theme and Year

If you want the search to be more specific then you can specify multiple search criteria. For instance one of the largest ranges is the Star Wars theme. Let’s have a look and see what sets have been released this year so far:

Get-BricksetSet -Theme 'Star Wars' -Year 2015 -OrderBy Pieces | Format-Table Name,Number,Theme,SubTheme,Year,Pieces -AutoSize



6) Get a Specific Set by Set Number

All Lego sets are assigned a number by Lego. Use the SetNumber parameter of Get-BricksetSet to retrieve details of a specific set.

Note: the API requires that you supply the set number in the format {number}-{variant}, e.g. 7199-1. If you see the number on the front of the box as say 7199, typically you will need to use 7199-1 for the first variant of that set. However, be careful as this will not always be the case.


Get-BricksetSet -SetNumber '7199-1'



7) Download Lego Set Instructions

The function Get-BricksetSetInstructions will return URLs for links to the set’s instructions on the Lego.com website.

Note: the parameter to use is SetId not SetNumber. SetId is Brickset’s own reference number for the set and not the Lego Set Number we used in the previous example. Use Get-BricksetSet to find this info first. I’ve used PowerShell pipeline parameter binding in the functions so that you can do this easily:

Get-BricksetSet -SetNumber '7199-1' | Get-BricksetSetInstructions


Note: this example returned two pdfs, since it is a large set and had two printed manuals in the box.

If you want to open them straight into your web browser of choice you could do this:

Get-BricksetSet -SetNumber 7199-1 | Get-BricksetSetInstructions | Select-Object -ExpandProperty url | Foreach-Object {Invoke-Expression “cmd.exe /C start $_”}

or if you wanted to say download all of the instructions for a particular theme you could do this using the built-in Windows cmdlet Start-BitsTransfer:

Get-BricksetSet -Theme 'Indiana Jones' | Get-BricksetSetInstructions | Select-Object -ExpandProperty url | ForEach-Object {$file = ($_.split('/'))[-1]; Start-BitsTransfer -Source $_ -Destination "C:\Users\jmedd\Documents\$file"}


8) Other Module Functions

There are a few other functions in the module for finding information around Images, Set Reviews and Recently Updated Sets.

I hope you have fun with this module :-)


PowerShell: Default Value of [Int]$a is 0

I didn’t realise until yesterday that the default value of a variable using the [int] type had a default value of 0, e.g



So what’s the big deal? Say you have a function as follows:

function Test-DefaultInt {





"a is $a"
 "b is $b"
 "c is $c"

and run it like so

Test-DefaultInt -a 5 -b 6 -c 7

Test-DefaultInt -a 5 -b 6

You get the following results:


If you change the function and take away the [int] from $c:

function Test-DefaultInt {





"a is $a"
"b is $b"
"c is $c"

and run the same tests you get the following:


with no value for c. OK, its a contrived example, but I had a reasonably complex situation to deal with. The difference between a variable being the value 0 or not present, inside the workings of the function, made a big difference to the output. Having wasted about an hour last night on it, I hope this saves someone else a headache :-)


PowerShell Requires -Modules: ModuleVersion “Argument must be constant”

I was looking to make use of a PowerShell feature which prevents a script from running without the required elements. Detailed here (about_Requires) there are examples for requiring specific versions of PowerShell, snap-ins and modules, and administrative rights.

In particular I was looking at the modules example given in the documentation:

#Requires -Modules PSWorkflow, @{ModuleName="PSScheduledJob";ModuleVersion=}

Unfortunately, using this example as is given generates an error Argument must be constant:

C:\Scripts\Scratch> .\Test-Requires.ps1
At C:\Scripts\Scratch\Test-Requires.ps1:1 char:20
+ #Requires -Modules PSWorkflow, @{ModuleName="PSScheduledJob";ModuleVersion=1.0.0 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Argument must be constant.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : RequiresArgumentMustBeConstant


The correct syntax for the example should read:

#Requires -Modules PSWorkflow, @{ModuleName="PSScheduledJob";ModuleVersion=""}

i.e. quotes around the ModuleVersion number. So in a contrived example where I bump the version number up to, running the script now gives me the response I am looking for:


I logged a documentation bug here.

PowerCLITools Community Module: Now on GitHub

Over the last few years I have built up a number of functions to use alongside the out of the box functionality in PowerCLI. I’ve posted some of the content before on this blog, but have at last got round to publishing all of the content that I am able to share, in a module available on GitHub – I’ve named it the PowerCLITools Community Module in the hope that some others might want to contribute content to it or improve what I have already put together.


This took a fair amount of effort since it is not possible for me to share everything that I have as part of my locally stored version of this toolkit. Some of it was developed by others I was working on projects with (and are not as necessarily so keen to share certain parts of their work) and some can’t be shared for commercial reasons. However, I found some time recently to split out everything that could be shared into a new module and also updated some of the code – typically to add some nice features in PowerShell v3 and later which weren’t available when a lot of the code was developed during PowerShell v2 days.

Since the content has been developed over a few years, consistency and standardisation of approach may not be 100% there. A quick look back over them showed some looking a bit dated – I have spent a bit of time tidying them up, but part of the reason for sharing them  was to take feedback and some prompting on where they could be improved. If I left them until I thought they were just right I’d probably never end up publishing them. So your feedback is the impetus I need to go and improve them :-)

A lot of the functions are there to fill in gaps in cmdlet coverage with PowerCLI and there are a few which I made more for convenience where I have bundled together a few existing cmdlets into one function. These don’t particularly add a lot of value, but maybe demonstrate how you can tighten up your scripts a bit


Ensure that VMware PowerCLI is installed. Functions have been tested against v5.8 R1.


1) Download all files comprising the PowerCLITools module. Ensure the files are unblocked and unzip them.
2) Create a folder for the module in your module folder path, e.g. C:\Users\username\Documents\WindowsPowerShell\Modules\PowerCLITools
3) Place the module files in the above folder

So it should look something like this:


The below command will make all of the functions in the module available

Import-Module PowerCLITools

To see a list of available functions:

Get-Command -Module PowerCLITools


Nested Modules

You will note that each function is itself a nested module of the PowerCLITools module. In this blog post I describe why I make my modules like this.

VI Properties

If you take a look inside the PowerCLITools.Initialise.ps1 file you’ll notice a number of VI Properties. Some of these are required by some of the functions in the module and some are just there for my convenience and make using my PowerCLI session simpler. You can add and remove VI Properties as to your own personal preference, but watch out that some are actually needed.  You can find out more about VI Properties here.


I really hope people find these functions useful. I have a number of ideas on where some can be improved, but please provide your own feedback as it’ll be the nudge I need to actually go and make the changes :-)

Get-Task: ID Parameter is Case Sensitive

There aren’t many occasions when you trip up in PowerShell because of something being case sensitive, it generally doesn’t happen since most things are typically not like that. I was working with the PowerCLI cmdlet Get-Task and in particular the ID parameter to do something like:

Get-Task -Id 'task-task-2035'

I had originally found the ID via:

Get-Task | Format-Table Name,ID -AutoSize

However, I received the error that no tasks of that ID were found :

Get-Task : 24/02/2015 20:51:57 Get-Task The identifier task-task-2035 resulted in no objects.
At line:1 char:1
+ Get-Task -Id task-task-2035
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-Task], VimException
+ FullyQualifiedErrorId : Client20_OutputTracker_ReportNotFoundLocators_LocatorNotProduced,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetTask

Turned out that making the task ID match the exact case worked:

Get-Task -Id 'Task-task-2035'

Apparently the IDs are case sensitive by design :-)

One to watch out for anyway…..

PowerCLI is now a Module!

We’ve been waiting for this a long time, but with the 6.0 release PowerCLI is now available as a module. Microsoft changed the way itself and third-parties should deliver PowerShell functionality back in PowerShell version 2 by offering modules. Previously in PowerShell version 1 additional functionality was available via snap-ins.

It’s not fully there yet, but some of the functionality is now available in a module. 6.0 will be a hybrid release, with the rest to follow later.

Notice how the Core functionality is in both lists since this is a hybrid release.

Get-Module *vmware* -Listavailable


Get-PSSnapin *vmware* -Registered


I believe there was significant effort in making this leap, so many thanks to Mr Renouf and his team :-)

How To Make Use Of Functions in PowerShell

Over the last few weeks I’ve had a number of comments on posts essentially asking the same question: “How do I use the functions that you publish on your blog?”. So I thought it worth making a post to refer people to, rather than trying to respond in kind to each comment. There are a number of ways it can be done depending on your requirements and they are listed below.

First of all, let’s create a simple function to use for testing:

function Get-TimesResult {

Param ([int]$a,[int]$b)

$c = $a * $b

Write-Output $c

1) Paste Into Existing PowerShell Session

If you are working interactively in the console then the function can be copy / pasted into that session and is then available for the duration of that session. I find this easier to do via the PowerShell ISE than the standard console.

Copy the function into the script pane:


Click the Green Run Script button or hit F5 and the code will appear in the console pane:


The function is now available for use and if using the ISE will appear interactively when you start typing the name:




2) PowerShell Profile

If the function is something that you wish to use regularly in your interactive PowerShell sessions then you can place the function in your PowerShell Profile and it will be available every time you open your PowerShell console.

If you are unsure what a PowerShell profile is or how to use one, there is some good info here. A quick way to create one is:

New-Item -Path $profile -ItemType File -Force

Once you have created a PowerShell profile, place the function in the profile and save and close. Now every time you open your PowerShell console the function will be available.


3) Directly In A Script

If you wish to use the function in a script, place the function in the script above the sections where you need to use it. Typically this will be towards the top. The plus side of doing it this way is everything is contained in one file, a negative is that if you have a number of functions then readability of the script is reduced since there may be a long way to scroll down before anything of significance starts to happen.


4) Called From Another Script

One method I have seen quite often in the wild (and I’m not a particular fan of, point 5 is a much better approach) is to store all regularly used functions in a script file and dot source the functions script file in the script where you need to use one or more of the functions.

Functions script file Tools.ps1:


Get-Results script file calling Tools.ps1:

Note the dot and a space before the reference to the Tools.ps1 file

. C:\Users\jmedd\Documents\WindowsPowerShell\Scratch\Tools.ps1

Get-TimesResult -a 6 -b 8



5) Stored in a Module

Using a PowerShell module is a more advanced and significantly more structured and powerful method of achieving what was done in 4). If you haven’t used PowerShell modules before I wrote an introduction to PowerShell modules a while back which you can find here.

Essentially they are a method to package up your reusable functions and make them available in a manner similar to how other teams in Microsoft and third-parties produce suites of PowerShell cmdlets for consumption.

For this example I have created a Tools module to use, which essentially is the same content as the Tools.ps1 file, but stored in a *.psm1 file (Tools.psm1) in the Modules\Tools folder on my workstation.

Note: the name of the *.psm1 file should match that of the folder. Its possible to create a more enhanced module than taking this approach using a Module Manifest, but we don’t need that for the purposes of this post. It’s described further in the previously mentioned article.


Now we can use the *-Module PowerShell cmdlets to work with our content.

To observe the module we can use Get-Module:

Get-Module Tools -ListAvailable


To use the functions contained in  the module we can use Import-Module

Import-Module Tools

Get-TimesResult -a 6 -b 8



Note: Since PowerShell v3 automatic cmdlet discovery and module loading has been supported. (You can find out more about it here) Consequently, you don’t actually need to use Import-Module to get access to the functions as long as you place the Module in the correct location. However, it would be a good practice to add the Import-Module line to your script, so that another user is aware of where you are getting the functionality from.

Improving the PowerShell ISE Experience with ISESteroids 2

For a long time I’ve used the built-in to Windows, PowerShell ISE for my PowerShell scripting experience. Most people tend to have a particular favourite editor for their coding, usually after trialling out a few different ones. For pretty much everything else I’ve settled on Sublime Text, but for PowerShell I use the ISE since I really like the integration with the PowerShell console.

The ISE was introduced in PowerShell 2.0 and to be honest was pretty basic back then. It’s  improved significantly since then into version 4, but still has some areas where there could be improvement or features missing that you would like to see.

Earlier in the year I tried out ISESteroids 1.0 which started to plug a number of the gaps I found in the ISE. Recently I had chance to upgrade to ISESteroids 2 and it has improved even further.

For a quick preview of what is available check out the below video.

A few things in it I particularly like:

1) More distinct (yellow) highlighting of bracket matching or other sections


(single click on this double quoted string)


2) Block commenting (this was a real annoyance for me – there is a keyboard shortcut to do it in the standard ISE, but still fiddly)



After pressing the single button below:




3) ScriptMap which allows you to easily navigate your way through long scripts



4) Manage Version History


Clicking on Compare opens WinMerge and a view of what has changed between versions


5)  Autoselection. Click repeatedly to select various code segments






6) Enhanced Debugging

Best explained in the following video

For a more in-depth look at some of the features, check out the below video with ISESteroids creator Dr Tobias Weltner and fellow PowerShell MVP Jeff Wouters.