Windows Server

System Center ConfigMgr 1702

Here we go again. New version of ConfigMgr! This time around it brings a bunch of new cool features and improvements. It also brings along the end of the 2008 era for site servers and SQL servers.

This is all good news but it requires some planning and managinig before an upgrade can be done if you are still running Windows Server 2008 or SQL server 2008.

For a complete list of what’s new and removed check out the official documentation here.


Happy deploying!


Keeping Track of PowerShell versions

In today enterprises many are faced with the challenge of managing both Windows 7, 8, 8.1 and 10. This means that most have a multitude of PowerShell versions out there which in turn does not ease the management tasks faced.

If you are running ConfigMgr 2012 or later you have access to one of my favorite features called Compliance Settings. Use this feature you can easily keep track of your environments different settings and measure compliance. One of the things I like to measure is the current running PowerShell version. I do this for two reasons. Number one, I want to now that my systems are running the version set out as a baseline. Number two is that if they are not running the correct version I get an easy way of finding them all and hence an easy way of correcting it.

So the tasks including creating a Configuration Item, linking it to a Configuration Baseline, deploying said baseline to a collection of workstations and creating a collection of devices that are not running the correct version.

Step 1 – Creating the Configuration Item

In your ConfigMgr console find the Assets and Compliance workspace and then under Compliance Settings you will find Configuration Items.

Create a new one and give it a name, I will be using “PowerShell Version”. Make sure that Settings for device managed with ConfigMgr Client is set to “Windows Desktops and Servers (custom)”.

In the next pane select the appropriate Operating Systems that this can be run on. Hint, Windows XP does not support PowerShell.

On the settings pane, hit New and in the configuration set a Name, again “PowerShell version” works just fine. Set the Setting type to “Script” and the datatype to Integer. Hit the “Add Script” button for Discovery script and paste in the following script and then hit OK.

[int]$Version = $PSVersionTable.PSVersion.Major
return $Version

On the Compliance Rules pane hit New and give the Rule a name. I’m calling it BaselineVersion. Hit the browse button and select your Current CI and the Version setting we just created. The rule type should be set to Value and in the comply part set the value returned must “Equal” and then set your desired baseline version. 4 will give you an OK on Windows 8.1 and Windows 10 and 5 will only give you an OK on Windows 10 (this assumes you have not previously upgraded your WMF versions). Hit OK and then Next.

Review your setting on the summary pane and hit next when ready to create the Configuration Item

Step 2 – Creating a Configuration Baseline

Head over to the Configuration Baselines workspace and create a new baseline. Please note this can both be included in previously created baselines but I prefer a separate for this so I can later use the non compliance feature. Give the Baseline a name, “PowerShell”. Hit Add, Select Configuration Item and select your previously created CI.

Step 3 – Deploying the Baseline

This should feel very normal to most of you since it’s the same procedure as deploying any application or client setting. Right click your baseline and select deploy. The wizard will not look like the usual deployment wizards but all you have to do is select a collection to deploy to. I recommend avoiding deploying it to the built-in collections and instead do two deployments if you want to monitor both servers and clients. Before you hit OK change the Schedule to suite your response times. Default is 7 days which in a small environment can be forever but in a large environment it just around the corner.

Step 4 – Creating the non compliant collection

The last step is to create that all needed collection which you can deploy the new Windows Management Framework too. select your newly created baseline, look for a tab named Deployments a the bottom of the console. In this view you can see the collection the baseline has been deployed to.

Now right click the collection, select “Create New Collection” and then select “Non-Compliant”. Follow the new Collection wizard and not that the rule for membership is premade.


Last notes

Now all that remains is waiting for the devices to report back status and then end up in the Non-Compliant collection so you can remedy them.

For your Windows 7 machines please note that if you have not previously upgraded Windows Management Framework you will need to install both WMF4 and WMF5. WMF4 is a prerequisite for WMF4 and both require a reboot to complete. This might be a good time for a small custom task sequence.



ConfigMgr–Disk Space Compliance

One of the least utilized features in ConfigMgr is compliance items and baselines. For some reason most of my customers tend to forget that a small part of monitoring on the client side will go a long way towards reducing the amount of tickets to your helpdesk.

One of things you might wish to measure is free space left of on the OS drive. This is easily done with a small compliance item. This post will show you how and you can then expand this to do self cleaning and other features as well if you so wish.

Start with creating a Compliance Item by going to the Asset and Compliance Node, Compliance Settings and Configuration Items. Right click, Create Configuration Item and give it a suitable name. Click Next when ready.


Select the Operating systems that this can run on. Make sure to deselect the older OSes which do not support PowerShell and click next when done.


In the settings pane click new to create a new setting to monitor. Give it a name I use FreeSpace and then set Setting type to Script and Data type to Integer.


Click Add Script and add the script to get the frees pace percentage of the C drive. Click OK and next to get to the Compliance Rules pane.


The Script

$FreeSpace = (Get-Volume -DriveLetter C).SizeRemaining/(Get-Volume -DriveLetter C).size
[int]$Size = [math]::Round($FreeSpace,2)*100
return $Size

Click New to add a new rule, give the Rule a name and select the setting you just created. For rule type set it to Value and set the following values:
The value returned by the script: Less than
The following values: <percent you wish to monitor> (I use 80)
Noncompliance severity for reports: Warning


Now the Configuration Item is done, just click next twice to save everything and create the CI.

For this to actually work a Baseline needs to be created. So head over to the Asset and Compliance workspace and the Compliance settings node and find Compliance Baselines. Right click and create a new baseline.

Give the baseline a name, click Add and select Configuration Item.


You get a list of all your CIs and just select the one you just created and click Add and OK.


Now you have a baseline you can deploy to a collection.

This can of course be expanded with things like non compliant collections, reports, remediation scripts and so on. You can also add other checks and verifications to the same baseline and monitor things like BitLocker encryption status.

WS2016 Beyond Unsupported

Update 2016-10-01: Currently MAK keys won’t work with activation. Expect Microsoft to release a new Eval media to correct this.

Update 2016-10-09: I previously had mentioned you can upgrade index 1 and 3 using the methods described below but Core editions cannot be modified this way and I have update the post to reflect that.

Windows Server 2016 Eval media has been released and while we wait for VL media there is a small cheat you can use if you want to play around with the licensing modes. Please do note that this is not in any way a supported way to do it and far from recommended.

Method 1 – An already running server with WS 2016 installed

This is the easier way and can be done on any running Windows Server 2016 except for domain controllers.

First you need to get the KMS keys from Microsoft TechNet KMS key appendix A found here There are different keys for both Standard and Datacenter so make sure pick the correct one.

Next start an elevated command prompt and run one of the following commands depending on if you upgrading to Standard or Datacenter

For Standard:
Dism /online /Set-Edition:ServerStandard /Productkey:<key for Standard from appendix A> /AcceptEULA /Norestart


For Datacenter:
Dism /online /Set-Edition:ServerDatacenter /Productkey:<key for Datacenter from appendix A> /AcceptEULA /Norestart


Wait while it completes and then reboot the server and your done. When the server is done rebooting you will have either a Standard edition or Datacenter Edition server.

Method 2 – Changing the media and enable in-place upgrade

This is a bit more complex and requires some installation steps before it works. The first thing needed is the newest Dism tools 10.0.14939 found in the ADK for Windows 10 1607. That can be found here

Download the setup for ADK and run the installation. The only component needed for this is the Deployment Tools. Wait for the installation to finish and then reboot the machine to make sure all dlls are registered.


Download the Eval media from the TechNet Evaluation Center

Copy the contents of the ISO to a folder on your management machine in this example I will use C:\ISO but you can use any folder, just make sure to correct all paths in each command.


Create a folder for mounting the wim file (C:\Mount) and start an elevated command prompt.

Change the directory to your newly installed dism tools usually here C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\DISM then run the following commands and press enter after each (there will be some wait in between each)

dism.exe /Mount-Wim /WimFile:C:\ISO\Sources\Install.wim /index:2 /MountDir:C:\Mount

dism.exe /Image:C:\Mount /Set-Edition:ServerStandard /ProductKey:WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY /AcceptEula /Norestart

dism.exe /UnMount-image /MountDir:C:\Mount /Commit

dism.exe /Mount-Wim /WimFile:C:\ISO\Sources\Install.wim /index:4 /MountDir:C:\Mount

dism.exe /Image:C:\Mount /Set-Edition:ServerDatacenter /ProductKey:CB7KF-BWN84-R7R2Y-793K2-8XDDG /AcceptEula /Norestart

dism.exe /UnMount-image /MountDir:C:\Mount /Commit

If you look closely you will notice I change the index number and the product key to update all 4 scenarios, Server Standard Core, Server Standard GUI, Datacenter Core and Datacenter GUI

Now the last step is the one you have to solve yourself and that is to create a bootable ISO from these files.


As a last note: DO NOT under any circumstances use this in production. I highly doubt this is a supported or even recommended way from Microsoft but can help you in your testing with licenses.

Happy deploying!


Windows Server 2016 Ref Image

Update 2016-10-20: VL media has been release and should be used for production environments. I have also added the servicing update for 2016 that is needed to get a more complete image.

During Ignite Windows Server 2016 was released as an Eval product. This means you can now download and start testing the RTM version of 2016 and prepare for when the volume license bits arrive sometime later this fall.

As with previous version of Windows Server it makes sense to create a reference image to include needed zero day patches and Visual C++ runtimes for any applications you might need to run.

To create a reference image we use Microsoft Deployment Toolkit and guidance on how to set that up can be found on TechNet here: The same principals for Windows 10 applies to Windows Server 2016 with a few differences.

So lets start with importing the operating system this is the same as on the client side, just keep in mind to keep the folder name short to avoid issues with filenames in subfolder getting to long.


Next we create the a Package folder and import the zero day patch with fixes for Storage Spaces Direct (S2D). The patch is at current writing missing a knowledge article but can be found in the update catalog. Search for KB3192366 or use this link

As KB3192366 is an update rollup you will also need the matching service stack update. For 2016 and Windows 10 that is KB3176936 found here

When the folder has been created and the patch imported it should look something like this


Continue with creating a Selection Profile to make sure that when the image is deployed only the relevant patches for WS2016 is imported. Expand the Advanced Configuration in MDT, select the node called Selection Profiles. Create a new profile and select the folder created in the step above.


We also need an application to install the Visual C++ runtimes to make it as easy as possible use the following from the friendly bunny


Next you need to create the task sequence by following the short wizard. When the sequence is created there are a couple of things to sort out.

First off we need to use the selection profile we created earlier. To do that open up the sequence and in the Preinstall section find the step called Apply Patches. To the right you will find a dropdown that is preset to All Packages, this needs to be changed to the Selection Profile created.


The second item to change is to turn on Windows Update in the sequence which is disabled by default. The two Windows Update steps can be found in the State Restore phase. Make sure to untick the Disable this step check box for each of them.


Add the C++ runtimes application to your sequence just above the first Windows Update step to make sure that any patches available for them will be applied as well.


The last thing is to change the default behavior of Windows Update. To to that we need to change a value in the unattend.xml file used by this sequence. Browse to your deployment share and to the Control folder. In here there will be a folder with the same name as the ID of your newly created sequence. Inside of that folder you will find the unattend.xml file, edit the file with Notepad or any other xml compatible editor.

Find the OOBE Section and the value called ProtectYourPC. Change the value from 1 to 3. This will disable Windows Update until MDT is ready to use it and MDT will the turn the feature back on.


That’s it your all set. This can now be run as part of your image factory setup, as a stand alone sequence with either VmWare or Hyper-V as the virtual machine platform.

If you want more information on the Image Factory check Mikes blog here

And if you want more detailed information on the setup and how to skip wizard panes during your reference image creation check Johan’s blog here

Happy deploying!


Datacenter – Change DNS Server

Let’s not kid ourselfs chaning dns servers happens. There is a new domain controller or someone moves the DNS to a new box with a new IP-address and the pesky job of changing all the primary and secondary DNS entrys on all your member servers has just got dropped into your lap.

Well there is a bright side. You can use PowerShell!

Posted below is a script that will change the primary and secondary dns server entry for a list of computers. The list can be either manual like this invoke-dnsserverchange.ps1 –computername –primarydns –secondarydns or it could be an txt file with all the server in it like so invoke-dnsserverchange.ps1 c:\myservers.txt –primarydns –secondarydns

By default the script will output logfile where it will list all the servers it has tried and notify you on the result for each. The script will not change dnsentries for servers with more than 1 network adapter. This is due to me having no control if you have a server with external dns on one side and internal on the other so those you need to change manually.

Since this requires PowerShell don’t forget that for Server 2008 and R2 you still need to enable and open the firewall for remote PowerShell for this to work.

The Script

Created:     2016-04-15
Version:     1.0
Author :     Peter Lofgren
Twitter:     @LofgrenPeter
Blog   :

This script is provided "AS IS" with no warranties, confers no rights and
is not supported by the author
  Change DNS Client address on a computer
  Sets new DNS client ip address on one or more computers
  Invoke-DnsServersChange.ps1 -ComputerName -PrimaryDns -SecondaryDNS
  Invoke-DnsServersChange.ps1 -ComputerName, -PrimaryDns -SecondaryDNS
  Invoke-DnsServersChange.ps1 -ComputerName C:\Servers.txt -PrimaryDns -SecondaryDNS
param (
  $LogFile = ".\DnsServers.log"
Add-Content -Path $LogFile -Value "Starting DNS set run at $(Get-Date -Format yyy-MM-dd) $(Get-Date -Format HH:mm)" -Force
Add-Content -Path $LogFile -Value "ComputerName,PrimaryDNS,SecondaryDNS,Result" -Force

if ((Test-path -Path $ComputerName) -eq $true) {
  $ComputerName = Get-Content -Path $ComputerName

if ($ComputerName.count -eq 1 -and $ComputerName -eq $env:COMPUTERNAME) {
  if ((Get-NetAdapter).count -ge 2) {
    $Result = "$env:COMPUTERNAME,FAILED,FAILED,Multiple Adapters found"
  Else {
    $InterfaceIndex = (Get-NetAdapter -Physical).InterfaceIndex
    Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses $PrimaryDNS,$SecondaryDNS
    $Result = "$env:COMPUTERNAME,$PrimaryDNS,$SecondaryDNS,SUCCESS"
  Add-Content -Path $LogFile -Value $Result -Force
Else {
  foreach ($Computer in $ComputerName) {
    if ($Computer -eq $env:COMPUTERNAME) {
      if ((Get-NetAdapter).count -ge 2) {
        $Result = "$env:COMPUTERNAME,FAILED,FAILED,Multiple Adapters found"
      Else {
        $InterfaceIndex = (Get-NetAdapter -Physical).InterfaceIndex
        Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses $PrimaryDNS,$SecondaryDNS
        $Result = "$env:COMPUTERNAME,$PrimaryDNS,$SecondaryDNS,SUCCESS"
      Add-Content -Path $LogFile -Value $Result -Force
    Else {
      $Result = Invoke-Command -ComputerName $Computer -ScriptBlock {
        param (
        if ((Get-NetAdapter).count -ge 2) {
          return "$env:COMPUTERNAME,FAILED,FAILED,Multiple Adapters found"
        Else {
          $InterfaceIndex = (Get-NetAdapter -Physical).InterfaceIndex
          Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses $PrimaryDNS,$SecondaryDNS
          return "$env:COMPUTERNAME,$PrimaryDNS,$SecondaryDNS,SUCCESS"
      } -ArgumentList $PrimaryDNS,$SecondaryDNS -ErrorAction SilentlyContinue
      if ($? -eq $false) {
        Add-Content -Path $LogFile -Value "$Computer,FAILED,FAILED,Failed to connect" -Force
      else {
        Add-Content -Path $LogFile -Value $Result -Force
Add-Content -Path $LogFile -Value "Finished DNS set run at $(Get-Date -Format yyy-MM-dd) $(Get-Date -Format HH:mm)"


Happy deploying!

WMF 5 in the reference image

Microsoft has finally released Windows Management Framework 5 in the rereleased version. This means its time to start adding in your reference image so you can benefit from it on new machines.

To do this I use a script and install it as an application in MDT. That way I only need on application for all OSes and the script will sort out how which installer to use.

To make this happen download the zip file from here and extract it. Download all the WMF files from Microsoft Download here and place each file in each of the OS folder.

Create a new application in MDT and give it a suitable name. The source directory is the folder you extracted to in which the Power Shell script file resides. For command line type in the following “PowerShell.exe -ExecutionPolicy ByPass -File Install-WMF5.ps1” without quotes.

Next we need to make a small change to the task sequence. Just before the Windows Update step (Pre-Application) I create a folder called Custom Applications. In here I place all my reference image applications. So you can see I install Microsoft Visual C++ Runtimes and Windows Management Framework 4. After WMF4 is installed add a Restart Computer step, then add your WMF5 application and another Restart Computer step after that.


Now you are all set. This will install WMF5 in your sequence so when that image is used WMF5 will be preinstalled without any need for reboots.

I know I haven’t covered WMF4 in this post and if you don’t have that already, let me know and I can do a write up about it as well. But you really should be installing it already 🙂

Happy deploying