Windows 10 Being Pushed Out To Domain-Joined PCs

Brad Sams (my boss at published a story last night about how Microsoft has started to push out Windows 10 upgrades to domain-joined PCs.

Note that the PC doesn’t upgrade via Windows Update; the user will be prompted if they want to update, and then a deliberately confusing screen “encourages” the user to upgrade.

Brad notes that the environment must meet certain requirements:

  • The machine must be running and licensed for Windows 7 Pro or Windows 8.1 Pro (Enterprise doesn’t do this stuff).
  • There is no WSUS, ConfigMgr, etc – the machine gets updates directly from MSFT – this means smaller businesses for the most part.
  • The machine must be a domain member.

As you can see, this affects SMEs with a domain (no WSUS, etc). But I’d be surprised if larger businesses weren’t targeted at a later point in order to help MSFT hit their 1 billion PCs goal.

In my opinion, this decision to push upgrades to business is exactly the sort of action that gives Microsoft such a bad name with customers. Most SMEs won’t know this is coming. A lot of SMEs run systems that need to be tested, upgraded, or won’t support or work on newer operating systems. So Microsoft opting to force change and uncertainty on those businesses that are least ready is down right dumb. Brad reports that Microsoft claims that people asked for this upgrade. Right – fine – let those businesses opt into an upgrade via GPO instead of the other way around. Speaking of which …

There is a blocker process. I work in a small business and I’ve deployed the blocker. Windows Update added new GPO options to our domain controllers, and I enabled the GPO to block Windows upgrades via Windows Update:


As you can see – I’ve deployed this at work. We will upgrade to Windows 10 (it’s already started) but we will continue to do it at our own pace because we cannot afford people to be offline for 2 hours during the work day while Windows upgrades.

Create a WS2016 Nano Server Hyper-V VM

Setting up a Nano Server VM requires running some PowerShell. The instructions that I found out there aren’t that clear for a non-PowerShell guru , are wrong, or are incomplete. So let me clear up everything by showing you exactly what I am using to deploy Nano Server as a Windows Server 2016 (TPv3/Technical Preview 3) Hyper-V virtual machine.

Note: The process will probably change after I published this post.

Step 1 – Make Folders

Create three folders on a computer with a fast disk. Note that I’ll use C: but maybe you should use a D: or something.

  • C:\Nano
  • C:\Nano\Base
  • C:\Scripts

Step 2 – Copy Scripts

Mount the WS2016 ISO – let’s assume that it mounts as E:. Copy two scripts from E:\NanoServer from the ISO to C:\Scripts:

  • new-nanoserverimage.ps1
  • convert-windowsimage.ps1

Step 3 – Dot The Scripts

Note that I missed out on this step because I had never encountered this sort of thing before – I’m an advocate of PowerShell but I’m no guru! If you do not run this step, New-NanoServerImage.ps1 will do nothing at all and wreck your head for 3 hours (it did for me!).

Open a PowerShell window with elevated privileges. Navigate to C:\Scripts. Run the following:

. .\convert-windowsimage.ps1

I know – it looks funny. Enter it exactly as above. This appears to load the contained script as a cmdlet that can later be executed.

Do the same again for New-NanoServerVHD.ps1:

. .\new-nanoserverimage.ps1

Now we can build a new VHD with Nano Server pre-installed.

Step 4 – Create a VHD

You can now run New-NanoServerImage. Here’s what I ran:

New-NanoServerImage -MediaPath e:\ -BasePath C:\Nano\Base -TargetPath C:\Nano\Nano1 -GuestDrivers -ComputerName "Nano1" -DomainName "prev.internal" -EnableIPDisplayOnBoot -AdministratorPassword (convertto-securestring -string "AVerySecurePassPhrase" -asplaintext -force) -EnableRemoteManagementPort -Language EN-US

The above will prep a VHD with a VM called Nano1. I have configured the VM to join the prev.internal domain – note that this will require me to have suitable domain creds – a computer account is created in the domain. I enabled the Hyper-V guest drivers and allowed the IP of the VM to appear on the console. The VHD will be stored in C:\Nano\Nano1. Note that if this folder exists then the process will abort:

WARNING: The target directory already exists. If you want to rebuild this image, delete the directory first.
WARNING: Terminating due to an error. See log file at:

Note that I had to specify EN-US because, at this time, my default region of EN-IE was not available:

WARNING: The ‘en-ie’ directory does not exist in the ‘Packages’ directory (‘g:\NanoServer\Packages’).
WARNING: Terminating due to an error. See log file at:

I could have added other roles/packages to the VHD such as:

  • -Storage: For a SOFS cluster.
  • -Compute: To enable Hyper-V … useful when TPv4 (we guess) introduces guest virtualization.
  • -Clustering: To enable failover clustering in the VM.
  • -Defender: Adding security to the guest OS.

A minute or so later, a 439 MB was created in the newly created C:\Nano\Nano1.

Recreating a Nano Server VM

If you’re playing with Nano Server in a lab then you’ll create VMs with name reuse. If you do this with domain join then you might encounter a failure:

WARNING: Failed with 2224.
WARNING: Terminating due to an error. See log file at:

Open the log and you’ll find:

Provisioning the computer…

Failed to provision [Nano1] in the domain [prev.internal]: 0x8b0.

It may be necessary to specify /REUSE when running

djoin.exe again with the same machine name.

Computer provisioning failed: 0x8b0.

The account already exists.

That’s one of those “ding-ding-ding aha!” moments. The computer account already exists in AD so delete the account and start over.

Creating Additional VMs

Once you have run the above process, C:\Nano\Base will be populated with files from the ISO (\NanoServer). This means that you can drop the -MediaPath flag and eject the ISO.

New-NanoServerImage -BasePath C:\Nano\Base -TargetPath C:\Nano\Nano2 -GuestDrivers -ComputerName "Nano2" -DomainName "prev.internal" -EnableIPDisplayOnBoot -AdministratorPassword (convertto-securestring -string "AVerySecurePassPhrase" -asplaintext -force) -EnableRemoteManagementPort -Language EN-US

Step 5 – Move the Computer Account

In AD, move the computer account for the new Nano server to the required OU so it get’s any requierd policies on the first boot – remember that this sucker has no UI so GPO and stuff like Desired State Configuration (DSC) will eventually be the best way to configure Nano Server.

Step 6 – Create a VM

The above process prepare a VHD for a Generation 1 virtual machine. Create a Generation 1 VM, and attach the VHD to the boot device. Connect to the VM and power it up. A couple of seconds will pass and a log in screen will appear:


Log in with your local admin or domain credentials and you’ll be greeted with the console. Note that I enabled the IP address to be displayed during the setup:


Step 7 – Manage the Nano Server VM

If you want to do some management work then you’ll need to:

  • Wait for the eventual remote management console that was quickly shown at Ignite 2015.
  • Use PowerShell remoting.
  • Use PowerShell Direct (new in WS2016).

If you have network access to the VM then you can use remoting:

Enter-PSSession -ComputerName Nano1 -Credential prev\administrator

Troubleshooting network issues with Nano Server can be a dog because there is no console that you can log into. However … you can use PowerShell Direct with no network access to the VM, via the Hyper-V guest OS integration components:

Enter-PSSession -VMName Nano1 -Credential prev\administrator

Tip: Most AD veterans start network troubleshooting with DNS – it’s nearly always the cause. In my lab, I have 3 domains, so 3 sets of DNS. My DHCP scope sets up on domain’s DNS server as the primary, and that can cause issues. Some PowerShell Direct to the VM with some Set-DnsClientServerAddress sorted things out.

Creating & Deploying Windows Server Containers Using NAT and PowerShell

This post will show you how to use PowerShell to deploy Windows Server Containers using Windows Server 2016 (WS2016) Technical Preview 3 (TPv3).

Note: I wanted to show you how to deploy IIS, but I found that IIS would only work on my first container, and fail on the others.

This example will deploy multiple containers running nginx web server on the same VM host. NAT will be used to network the VMs using a private IP range on the VM host’s internal virtual switch.

Note: The VM host is created at this point, with a working NATing virtual switch that has an IP range of, with assigned to the VM host.

Create the nginx Container Image

The beauty of containers is that you create a set of reusable container images that have a parent child relationship. The images are stored in a flat file repository.

Note: In TPv3, the repository is local on the VM host. Microsoft will add a shared repository feature in later releases of WS2016.

Log into the VM host (which runs Server Core) and launch PowerShell


In this example I will create a new container using the default WindowsServerCore container OS image. Note that I capture the instance of the new container in $Container; this allows me to easily reference the container and it’s attributes in later cmdlets:

$Container = New-Container -Name nginx -ContainerImageName WindowsServerCore -SwitchName "Virtual Switch"

The container is linked to the virtual switch in the VM host called “Virtual Switch”. This virtual switch is associated with the VM’s sole virtual NIC, and sharing is enabled to allow the VM to also have network connectivity. The switch is enabled for NATing, meaning that containers that connect to the switch will have an IP of 192.168.250.x (in my setup). More on this stuff later.

Start the new container:

Start-Container $Container

Wait 30 seconds for the container to boot up and then remote into it:

Enter-PSSession -ContainerId $Container.ContainerId -RunAsAdministrator

I would normally use IIS here, but I had trouble with IIS in Windows Server Containers (TPv3). So instead, I’m going to deploy nginx web server. Run the following to download the installer (zip file):

WGet -Uri '' -OutFile "c:\"

The next command will expand the zip file to  c:\nginx-1.9.3\

Expand-Archive -Path C:\ -DestinationPath c:\ -Force

There isn’t really an installer. nginx exists as an executable that can be run, which you’ll see later. The service “install” is done, so now we’ll exit from the remote session:


We now have a golden container that we want to capture. To do this, we must first shut down the container:

Stop-Container $Container

Now we create a new reusable container image called nginx:

New-ContainerImage -Container $Container -Publisher AFinn -Name nginx -Version 1.0

The process only captures the differences between the original container (created from the WindowsServerCore container OS image) and where the machine is now. The new container image will be linked to the image that created the container. So, if I create a container image called nginx, it will have a parent of WindowsServerCore.


I’m done with the nginx container so I’ll remove it:

Remove-Container $Container –Force

Deploying A Service Using A Container

The beauty of containers is how quick it is to deploy a new service. We can deploy a new nginx web server by simply deploying a new container from the nginx container image. All dependencies, WindowsServerCore in this case, will also be automatically deployed in the container.

Actually, “deploy” is the wrong word. In fact, a link is created to the images in the repository. Changes are saved with the container. So, if I was to add content to a new nginx container, the container will contain the web content, and use the service and OS data from the nginx container image in the repository, and OS stuff from the VM host and the container OS image in the repository.

Let’s deploy a a new container with nginx. Once again I will store the resulting object in a variable for later use:

$Web2 = New-Container -Name Web2 -ContainerImageName nginx -SwitchName "Virtual Switch"

Then we start the container:

Start-Container $Web2

Wait 30 seconds before you attempt to remote into the container:

Enter-PSSession -ContainerId $Web2.ContainerId –RunAsAdministrator

Now I browse into the extracted nginx folder:

cd c:\nginx-1.9.3\

And then I start up the web service:

start nginx

Yes, I could have figured out how to autostart ngnix in the original template container. Let’s move on …

I want to confirm that nginx is running, so I check what ports are listening using:

NetStat –AN

I then retrieve the IP of the container:


Remember that the container lives in the NAT network of the virtual switch. In my lab, the LAN is My VM host has configured (Install-ContainerHost.ps1) as the NAT range. In this case, the new container, Web2 has an IP of

I then exit the remote session:


There’s two steps left to allow HTTP traffic to the web service in the container. First, we need to create a NAT rule. The container will communicate on the LAN via the IP of the VM host. We need to create a rule that says that any TCP traffic on a select port (TCP 82 here) will be forwarded to TCP 80 of the container ( Run this on the VM host:

Add-NetNatStaticMapping -NatName "ContainerNat" -Protocol TCP -ExternalIPAddress -InternalIPAddress -InternalPort 80 -ExternalPort 82

Finally, I need to create a firewall rule in the VM host to allow inbound TCP 82 traffic:

New-NetFirewallRule -Name "TCP82" -DisplayName "HTTP on TCP/82" -Protocol tcp -LocalPort 82 -Action Allow -Enabled True

Now if I open up a browser on the LAN, I should be able to browse to the web service in the container. My VM host has an IP of so I browse to and the default nginx page appears.

Deploy More of the Service

OK, we got one web server up. The beauty of containers is that you can quickly deploy lots of identical services. Let’s do that again. The next snippet of code will deploy an additional nginx container, start it, wait 30 seconds, and then log into it via session remoting:

$Web3 = New-Container -Name Web3 -ContainerImageName nginx -SwitchName "Virtual Switch"

Start-Container $Web3

Sleep 30

Enter-PSSession -ContainerId $Web3.ContainerId -RunAsAdministrator

I then start nginx, verify that it’s running, and get the NAT IP of the container (

cd c:\nginx-1.9.3\

start nginx

NetStat -AN



Now I can create a NAT mapping for the container in the networking of the VM host. In this case we will forward traffic to TCP 83 to (the container):

Add-NetNatStaticMapping -NatName "ContainerNat" -Protocol TCP -ExternalIPAddress -InternalIPAddress -InternalPort 80 -ExternalPort 83

And then we open up a firewall rule on the VM host to allow inbound traffic on TCP 83:

New-NetFirewallRule -Name "TCP83" -DisplayName "HTTP on TCP/83" -Protocol tcp -LocalPort 83 -Action Allow -Enabled True

Now I can browse to identical but independent nginx web services on container 1 on and, all accomplished with very little work and a tiny footprint. One might be production. One might be test. I could fire up another for development. And there’s nothing stopping me firing up more to troubleshoot, branch code, and test upgrades, and more, getting a quick and identical deployment every time that I can dump in seconds:

Remove-Container $Web2, $Web3

If you have apps that are suitable (stateless and no AD requirement) then containers could be very cool.

“Install-WindowsFeature : An unexpected error has occurred” Error When You Run Install-WindowsFeature In A Windows Server Container

This is one of those issues that makes me question a lot of step-by-step blog posts on Windows Server Containers that are out there – plenty of people were quick to publish guides on containers and didn’t mention encountering this issue which I always encounter; I suspect that there’s a lot of copy/pasting from Microsoft sites with little actual testing in a rush to be first to publish. It’s clear that many bloggers didn’t try to install things in a container that required administrator rights, because UAC was blocking those actions. In my case, it was installing IIS in a Windows Server 2016 (WS2016) Technical Preview 3 (TPv3) container.

In my lab, I created a new container and then logged in using the following (I had already populated $Container by  returning the container object into the variable):

Enter-PSSession -ContainerId $Container.ContainerId -RunAsAdministrator

And then I tried to install some role/feature, such as IIS using Install-WindowsFeature:

Install-WindowsFeature -Name Web-Server

I logged in using -RunAsAdministrator so I should have no issues with UAC, right? Wrong! Because the installation fails as follows:

Install-WindowsFeature : An unexpected error has occurred. The system cannot find the file specified.  Error: 0x80070002
+ CategoryInfo          : InvalidResult: (@{Vhd=; Credent…Name=localhost}:PSObject) [Install-WindowsFeature], Exception
+ FullyQualifiedErrorId : RegistryKey_OpenSubKey_Failed,Microsoft.Windows.ServerManager.Commands.AddWindowsFeatureCommand


What’s the solution? When you are remoted into the container you need to raise your administrator privileges to counter UAC. You can do this as follows, after you log into the container:

Start-Process Powershell.exe -Verb runAs

Run Install-WindowsFeature now and it will complete.



Note: I have found in my testing that IIS behaves poorly in TPv3. This might be why Microsoft’s getting started guides on MSDN use nginx web server instead of IIS! I’ve confirmed that nginx works perfectly well.

Why Are My Windows Server Containers Not On The Network?

I find containers are easy to create and it’s pretty simple to build a library of container images. At least, that’s what I found when I got to play with containers for the first time on a pre-build Windows Server 2016 (WS2016) Technical Preview 3 (TPv3) lab. But I started playing with containers for the first time in my own lab in the last few days and I had some issues; the thing I had never done was create a host, a VM host to be precise (a Hyper-V VM that will host many containers), by myself. In this post I’ll explain how, by default, my containers were not networked and how I fixed it. This post was written for the TPv3 release, and Microsoft might fix things in later releases, but you might find some troubleshooting info that might be of help here.

Some Theory

I guess that most people will deploy Windows Server containers in virtual machines. If you work in the Hyper-V world then you’ll use Hyper-V VMs. In this timeframe the documented process for creating a VM host is to download and run a script called New-ContainerHost.PS1. You can get that by running:

wget -uri -OutFile New-ContainerHost.ps1

You’ll get a script that you download and then you’re told by Microsoft and every other blog that copied & pasted without testing to run:

.\New-ContainerHost.ps1 –VmName <NewContainerHostVMName> -Password <NewContainerHostVMPassword>

What happens then?

  • A bunch of stuff is downloaded in a compressed file, including a 12 GB VHD called WindowsServer_en-us_TP3_Container_VHD.vhd.
  • The VHD is mounted and some files are dropped into it, including Install-ContainerHost.ps1
  • A new VM is created. The C: drive is a differencing VHD that uses the downloaded VHD as the parent
  • The VM is booted.
  • When the VM is running, Install-ContainerHost is run, and the environment is created in the VM.
  • Part of this is the creation of a virtual switch inside the VM. Here’s where things can go wrong by default.
  • The script completes and it’s time to get going.

What’s the VM switch inside a VM all about? It’s not just your regular old VM switch. It’s a NATing switch. The idea here is that containers that will run inside of the VM will operate on a private address space. The containers connect to the VM switch which provides the NATing functionality. The VM switch is connected to the vNIC in the VM. The guest OS of the VM is connected to the network via a regular old switch sharing process (a management OS vNIC in the guest OS).

What Goes Wrong?

Let’s assume that you have read some blogs that were published very quickly on the topic of containers and you’ve copied and pasted the setup of a new VM host. I tried that. Let’s see what happened … there were two issues that left me with network-disconnected containers:

Disconnected VM NIC

Almost every example I saw of New-ContainerHost fails to include 1 necessary step: specify the name of a virtual switch on the host to connect the VM to. You can do this after the fact, but I prefer to connect the VM straight away. This cmdlet adds a flag to specify which host to connect the VM to. I’ve also added a cmdlet to skip the installation of Docker.

.\New-ContainerHost.ps1 –VmName <newVMName> –Password <NewVMPassword> -SkipDocker –SwitchName <PhysicalHostSwitch>

This issue is easy enough to diagnose – your VM’s guest OS can’t get a DHCP address so you connect the VM’s vNIC to the host’s virtual switch.

New-NetNat Fails

This is the sticky issue because it deals with new stuff. New-NetNat will create:

… a Network Address Translation (NAT) object that translates an internal network address to an external network address. NAT modifies IP address and port information in packet headers.

Fab! Except it kept failing in my lab with this error:

Net-NetNat : No Matching interface was found for prefix (null).


This wrecked my head. I was about to give up on Containers when it hit me. I’d already tried building my own VM and I had downloaded and ran a script called Install-ContainerHost in a VM to enable Containers. I logged into my VM and there I found Install-ContainerHost on the root of C:. I copied it from the VM (running Server Core) to another machine with a UI and I edited it using ISE. I searched for and found a bunch of stuff for parameters. A variable called $NATSubnetPrefix was set to “”.

There was the issue. My lab’s network address is; this wasn’t going to work. I needed a different range to use behind the NATing virtual switch in the container VM host. I edited the variable to define a network address for NATing of “”:



I removed the VM switch and then re-ran Install-ContainerHost in the VM. The script ran perfectly. Let’s say the VM had an address of I logged in and created a new container (the container OS image is on the C:). I used Enter-PSRemote to log into the container and I saw the container had an IP of This was NATed via the virtual switch in the VM, which in turn is connected to the top-of-rack switch via the physical host’s virtual switch.

Sorted. At least, that was the fix for a broken new container VM host. How do I solve this long term?

I can tell you that mounting the downloaded WindowsServer_en-us_TP3_Container_VHD.vhd and editing New-ContainerHost there won’t work. Microsoft appears to download it every time into the differencing disk.

The solution is to get a copy of Install-ContainerHost.PS1 (from the VHD) and save it onto your host or an accessible network location. Then you run New-ContainerHost with the –ScriptPath to specify your own copy of Install-ContainerHost. Here’s an example where I saved my edited (the new NAT network address) copy of Install-ContainerHost on CSV1:

.\New-ContainerHost.ps1 –VmName NewContainerVM –Password P@ssw0rd -SkipDocker -SwitchName SetSwitch -ScriptPath "C:\ClusterStorage\CSV1\Install-ContainerHost.ps1"

That runs perfectly, and no hacks are required to get containers to talk on the network. I then successfully deployed IIS in a container, enabled a NATing rule, and verified that the new site was accessible on the LAN.

Microsoft News – 7 September 2015

Here’s the recent news from the last few weeks in the Microsoft IT Pro world:


Windows Server


System Center


Office 365



  • Meet AzureCon: A virtual event on Azure on September 29th, starting at 9am Pacific time, 5pm UK/Irish time.

Prevent Windows From Downloading Broken Drivers From Windows Update

Edit: the solution here does not work. The Windows Update Blocker offers a solution that works until Microsoft releases a new broken version of the broken driver. Frustrated much?

The release of Windows 10 has reminded many of us that Windows Update is usually the worst place to get a driver for your device, be it an Intel HD graphics adapter in your tablet or laptop, or a NIC in a Hyper-V host. The best driver always comes from the maker of your computer (HP, Dell, Lenovo, etc) because they distribute drivers for your specific and,  usually, customised chipset.

Recently I upgraded my 2 ultrabooks, a Lenovo Yoga S1 and a Toshiba KIRAbook, from Windows 8.1 to Windows 10. A trip to Device Manager found that the Intel HD graphics cards were broken and I was unable to share my display – projectors are a big part of my job!

I found a fix – but then a day or two later Windows Update decided to reapply Microsoft’s distribution of the driver and I was stuck once again with broken Ultrabooks. I took to Twitter and then I got a response from a Microsoft employee with a solution that should work.

Method 1 – Manual Change

Open up System > Advanced System Settings > Hardware > Device Installation Settings.  Set it to No, Let Me Choose What To Do and set Never Install Driver Software From Windows Update.


Method 2 – The Registry

Open REGEDIT and set both of these REG_DWORD values to 0:

  • HKLM\SOFTWARE\MICROSOFT\Windows\CurrentVersion\DriverSearching\SearchOrderConfig
  • HKLM\SOFTWARE\MICROSOFT\Windows\CurrentVersion\Device Metadata\PreventDeviceMetadataFromNetwork

Method 3 – Group Policy

The above are fine if you have one or two machines to modify, but what if you have dozens or hundreds of machines to update? Hopefully these machines are domain members; if so then you can deploy a GPO to them to make the required changes.

Look for a setting called Specify Search Order For Device Driver Locations in Computer Configuration > Administrative Templates > System > Device Installation. Enable the policy and set Select Search Order to Do Not Search Windows Update.


You should also enable Prevent Device Metadata Retrieval From The Internet at the same location in GPO.


Updating Drivers

Yes, you do need to update drivers – drivers and firmware are the cause of many issues on PCs, Hyper-V hosts, etc. On my PCs/laptops I install the OEM’s updating tool and regularly run a check/update. So where can you get drivers from in a larger environment. Well; always form the OEM. How do you distribute them?

  • Manually
  • A shared folder
  • Cluster Aware Updating – see what Dell has done
  • System Center, possibly even with OEM additions

Microsoft News 13-August-2015

Hi folks, it’s been a while since I’ve posted but there’s a great reason for that – I got married and was away on honeymoon 🙂 We’re back and trying to get back into the normal swing of things. I was away for the Windows 10 launch, happily ignoring the world. Windows 10 in the businesses is not a big deal yet – Microsoft needs to clear up licensing and activation for businesses before they’ll deliberately touch the great new OS – I’ve already had customers say “love it, but not until we get clarification”.


Windows Server



System Center

Office 365


Microsoft News – 16 July 2015

It’s been a busy week with WPC driving announcements that affect partners.


Windows Server

Windows Client



System Center

  • Datazen Enterprise Server: Datazen Enterprise Server is a collection of web applications and Windows services. Acts as a repository for storing and sharing dashboards and KPIs.

Office 365



Microsoft News–13 July 2015

I don’t have all that much for you, but the big news is the Azure Site Recovery (ASR, Microsoft’s DR site in the cloud) now supports VMware virtual machines and physical servers, without using System Center. You do need to run some stuff on-prem and in the cloud to make it work though, so there will be a tipping point where the solution becomes affordable.



System Center

Office 365