VisualStudio and ISE Steroids Vertical Guides

To make it easier for reviewers and other programmers to read PowerShell code it is recommended that lines of PowerShell code don’t exceed 100 characters. If you run past this limit you should usually split the line using a backtick (`). I also find that this limit prompts me to rethink my code logic if the line gets too long. Besides, no one wants to have to scroll several pages horizontally to be able to read your whole line of code.

However, one of the most common issues I run into when reviewing (or writing my own) PowerShell DSC resources is going over the 100 character limit. For your own projects you’re most welcome to use any styles that you want (although I’d still recommend this one for the reasons above). However, if you’re going to commit this code to the PowerShell DSC community resources you’ll need to ensure your code meets this requirement, otherwise reviewers will likely ask you change it.

But there is an easy way to help identify this problem if you’re using Visual Studio Code or PowerShell ISE Steroids: Setup a vertical guide/ruler at 100 characters.


A nice easy to see vertical ruler/guide tells us when our lines get too long… oh dear this line is too long.

To Set up a Vertical Ruler in Visual Studio Code

  1. Select User Settings (you can use Workspace Settings if you want) from Preferences in the File menu:
  2. Your user settings.json file will load on the right, with the Default Settings on the left:
  3. Add the following line to your settings.json file in between the braces:
    "editor.rulers": [100]


  4. Save the file and restart Visual Studio Code.

To Set up a Vertical Ruler in ISE Steroids

  1. Select Show Secondary Toolbar from the View menu.ss_verticalruler_isesteroidsmenu
  2. Click the Vertical Guides button and select Global Guide…ss_verticalruler_isesteroidsverticalguidebutton
  3. Enter 100 in the input box and press enter.


    The vertical guide is added – better fix that long line!

That is all there is to using vertical guides. Having them setup if you’re planning on committing code to a community project might save you some extra commits and help the community reviewers merge your code faster.

Happy coding!



Bulk Updating Nano Servers using PowerShell and CIM


Feel free to skip this introduction and jump down to the Updating via CIM section to see the actual update process.

Yesterday, I decided to connect up my Windows Server 2016 TP5 Active Directory lab up to the new Azure Server Management Tools. This was mainly to look at the experience with managing Nano Server using these new Azure based tools.


The interface is very slick, as you’d expect from anything managed within the new Azure Portal.

I did run into a minor glitch when installing updates, but the team over at Azure (major thanks @BrendanPower) had the problem identified and solved within 24 hours (and was rolled out while I was writing this post). Also remember, this is a Azure Preview Feature updating a Windows Server 2016 Technical Preview 5 operating system, so you’d expect a few glitches. I did a lot of experimenting with these new features and this is the only thing I ran into. I’m still extremely impressed with the responsiveness of the team over there in Redmond.

In fact while I was writing this very post I was contacted to let me know the fix had gone in to production and it worked perfectly:


Anyway, this post isn’t about how to configure an Azure Server Management Tools Gateway (it is extremely easy, but if anyone would be interested in a video let me know and I’ll make one), it is about updating Nano Servers using CIM and by extension updating lots of servers in one go.

Updating via CIM

In Windows Nano Server TP4 Microsoft included CIM cmdlets. This enabled us to use the root/Microsoft/Windows/WindowsUpdate CIM Namespace to use Windows Update to install updates on a Nano Server. After a bit of searching around I found this blog post covering the process.

However, I have lots of Nano Servers and updating them one at a time would be a real pain. So I decided to write a short PowerShell snippet to update all of them at once. This snippet should actually work with any Windows Server 2016 TP4 (or greater) version.

This snippet contains a simple function that takes three parameters:

  • Credential – this is the credentials to use to connect to the Nano Server and update it. If not passed you will be presented with a login dialog asking for them. It is assumed that all servers being updated use the same credentials.
  • Servers – this is the array of server names to apply updates to.
  • Install – setting this optional switch will cause the updates to be installed. If it is not set you will just be told for each server the list of updates that are required.
  • Restart – this optional switch will cause the servers to automatically restart after updates are installed (even if they don’t technically need a restart). Only set this switch if the Install switch is set.

For example, calling the function with:

Get-AvailableUpdates `
    -Servers 'SA-NANO1','SA-NANO2','SA-NANO3','SA-NANO4','SA-NANO5','SA-NANO6','SA-NANO7','SA-NANO8'

Would show the update status of the eight listed Nano Servers and show any updates available to be installed:


However, adding an -install parameter to the call:

Get-AvailableUpdates `
    -Servers 'SA-NANO1','SA-NANO2','SA-NANO3','SA-NANO4','SA-NANO5','SA-NANO6','SA-NANO7','SA-NANO8' `

Will cause all available updates to be installed onto the listed Nano Servers:


You may still need to restart these servers after the updates are installed. If you run the function again without restarting the servers first you will be told the updates still need to be installed. If you want the servers to automatically be restarted, add a -restart parameter:

Get-AvailableUpdates `
    -Servers 'SA-NANO1','SA-NANO2','SA-NANO3','SA-NANO4','SA-NANO5','SA-NANO6','SA-NANO7','SA-NANO8' `
    -Install `

Like this:


This is even more useful when you consider that you can update standard (Core and GUI) Windows Server 2016 installations like this as well. This might also work on earlier versions of Windows Server (2012, 2012 R2) as well, but I don’t have time to try this out.

Edit: 21 May 2016 – I tested this on Windows Server 2012 R2, but it does not work because the required CIM classes are not available on that version Operating System.

Note: I really haven’t put much work into error checking or reporting on this process, so if you run into any errors (servers not online, bad credentials etc) then they might not be handled elegantly. This code is really an example of what can be easily done.

This function would be a definite candidate for a PowerShell Workflow – allowing complete parallelization of the process.

I hope this is useful and have a great weekend!


cDFS is dead, long live xDFS

The xDFS DSC resource module has been officially released to the PowerShell Gallery thanks to the awesome review efforts of the Microsoft PowerShell Team. The cDFS DSC Resource has now been unlisted from the PowerShell Gallery. So now is the time to update any DSC configuration scripts to use xDFS.


Important: There were some minor changes to xDFS when it was converted from cDFS. For information on what you’ll need to change to convert to xDFS see my earlier post.


Using a Windows Virtual NAT with a Hyper-V Lab

One of the new features introduced into Windows in build 10586 and above was the new NAT Virtual Switch. This feature was primarily introduced to ease the introduction of the Windows Containers in the upcoming release of Windows Server 2016.

In more recent builds of Windows (build 14295 and above) the NAT Virtual Switch has been removed in favor of a new Virtual NAT Device that exists separate from the Hyper-V Virtual Switch.

This new Virtual NAT Device is more inline with Microsoft’s Software Defined Networking approach. It also allows us to create multiple Hyper-V Lab environments where each Lab is completely isolated from any others but still be connected to the Internet by way of the Virtual NAT Device.

Previously, to give all the machines in a Lab internet access we would have had to use:

  • An External Switch – Connect all machines to an External Virtual Switch that was connected to the internet via one of the Hyper-V Host’s network adapters.
  • A Guest NAT – Install a NAT onto one of the Guest Virtual Machines in the Lab. For example, install Windows Server 2012 R2 with the Remote Access role and configure a NAT. This would still require at least this node in the Lab to be connected to the internet via an External Virtual Switch.

Each of these approaches had some drawbacks:

  1. Each Lab was not completely isolated from the other labs.
  2. An entire guest might need to be provisioned to provide internet access to the other machines in the Lab.

But using the Virtual NAT device allows us to configure Labs with complete network isolation but still being connected to the internet without the use of a guest NAT.


So, to configure a pair of Labs like in the diagram above all we need is to execute a few PowerShell Cmdlets.

Note: Make sure your Hyper-V host is at least build 14295 (Windows 10 build 14295 or Windows Server 2016 TP5). Otherwise these cmdlets will fail.

If you want some more detail on setting up a Virtual NAT, see Set up a NAT Network.

Configure Hyper-V Lab with NAT

To configure a Hyper-V Lab with NAT, perform the following steps, executing any PowerShell cmdlets in an Administrator PowerShell console.

  1. Create a Hyper-V Internal Virtual Switch on your Host:
    New-VMSwitch -Name Lab1 -SwitchType Internal

    This will also create a Virtual Network Adapter connected to the host.

  2. Assign the gateway IP address of the NAT to the Virtual Network Adapter:
    # Get the MAC Address of the VM Adapter bound to the virtual switch
    $MacAddress = (Get-VMNetworkAdapter -ManagementOS -SwitchName Lab1).MacAddress
    # Use the MAC Address of the Virtual Adapter to look up the Adapter in the Net Adapter list
    $Adapter = Get-NetAdapter | Where-Object { ($_.MacAddress -replace '-','') -eq $MacAddress) }
    New-NetIPAddress –IPAddress -PrefixLength 24 -InterfaceIndex $Adapter.ifIndex
  3. Create the Virtual NAT device:
    New-NetNat –Name Lab1NAT –InternalIPInterfaceAddressPrefix
  4. Configure the network settings on each guest virtual network adapter assigned to the virtual switch in the subnet and configure the default gateway to be

That’s it – all machines in the Lab should have access to the internet and be completely isolated as well. Naturally I have updated the LabBuilder system to support this new functionality as well.

I hope this was useful and happy NATing.

cDFS moving to the PowerShell Team

Just a Friday afternoon heads up – if you’re using the cDFS DSC Resource I created to manage Windows Server Distributed File System (Replication and Namespaces), it has now been accepted into the PowerShell Community resources and will be under the control of the PowerShell Team.

This means that the GitHub source code repository will be moving over to the PowerShell organization in the next few days. This also means that any future releases of this resource module won’t be provided by me as cDFS, but will be released by the PowerShell team as xDFS.

So I recommend that when this happens you switch over to using the xDFS resource. I will put another post up here when the change over officially occurs. The first official release version under the new xDFS name will be 3.0.0.x. I won’t make any further changes or bug fixes to the cDFS resources.

It is also worth noting that as part of this move some minor changes were made to the DSC Resource modules. These are breaking changes and you will most likely need to update any DSC Configurations depending on this, but you would have to do this anyway because of the name change.

The changes are:

  • Resource xDFSRepGroup renamed to xDFSReplicationGroup
  • Resource xDFSRepGroupConnection renamed to xDFSReplicationGroupConnection
  • Resource xDFSRepGroupFolder renamed to xDFSReplicationGroupFolder
  • Resource xDFSRepGroupMembership renamed to xDFSReplicationGroupMembership
  • xDFSReplicationGroupConnection:
    • Changed DisableConnection parameter to EnsureEnabled.
    • Changed DisableRDC parameter to EnsureRDCEnabled.

These changes should only require minor changes to your configuration scripts to implement.

Thanks for reading and have a great Friday~