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.



Windows 10 Notes From The Field – Q&A

Last week @jarwidmark and myself held a live session about windows 10 deployment notes from the field and we had ALOT of good questions.

Here are the questions and answers from the session

Q: How well does the performance of an NVMe drive compare to an M2 SSD?
A: There are both M2 NVMe and M2 SSD drives available at the current time. However, the NVMe drives are a different type of drives even if they are connected using the slot type. NVMe will always be faster but depending on what you need to do it might not be economical.

Q: Can Secure Boot be disabled and enabled after Windows 10 installation?
A: Yes, Secure Boot can be disabled/enabled after Windows installation. Note that turning UEFI on/off is not the same thing!

Q: Is peercache similar to a product such as 1E Nomad?
A: Yes, peerchache is very similar to those types of products. What you need to remember is that peercache has now been around for all of 2 months while products similar third party products have been out for a couple of years. There is a good write up about this topic made by 2Pint Software found here

Q: What’s the best way to upgrade from Windows 7 to Windows 10 1607 in place?
A: As of right now the best way is using the Replace scenario so backup the current computer and redeploy it as a new computer while restoring the settings and documents. This will enable you to turn on UEFI+SecureBoot and any other new features you desire.

If you do a normal in-place upgrade there is currently no way of switching from Legacy BIOS to UEFI and thus you will not be able to use all the new cool features of Windows 10.

Q: how do you prevent Windows 10 from automatically uninstalling software it deems “not compatible” when doing Windows update? Example: Cisco VPN client app, when updating versions (i.e. 1507->1511)
A: Don’t use Windows Update, use sequencing instead. Either with MDT or SCCM. That way you can control before, during and after. Giving you the tools you need to get the job done. In this case making sure the software is reinstalled or upgrade as part of the in-place upgrade.

A good starting point can be found here

Q: For the in-place upgrade Task Sequence, is it possible to add Cumulative Update to the image rather than adding the CU to the TS? Running a Cumulative Update during the TS adds a lot of time to the deployment.
A: Yes, you can add both CUs and Security fixes to a install.wim file. That is fully supported. However, as it will use offline servicing to do so the patches won’t be installed until the machine is booted up and during the initial boot they will install. This will take the same amount of time as adding them as applications during the TS.

Q: Which OSs are supported by MDT 8443?
A: Windows 7 and forward. Note that MDT 8443 requires ADK1607 and that ADK has issues with Windows 7 and driver injection when running on SSD drives.

Q: Is the best way to customize default pinned apps in the Win 10 task bar still via a run-once logon script?
A: No, use the start and taskbar layout xml file instead. More info on that can be found here

Note that taskbar pinning using xml requires Windows 10 1607.

Q: Have you seen any new hardware components with no Win7 drivers?
A: Yes, not all new models support Windows 7. This is due to instruction sets in some of the Skylake CPUs by Intel. Most vendors have a number of models/configurations that do support Windows 7 still. Expect this to diminish now that Kaby Lake is out and going forward with new CPUs.

Q: With Win 7/8.1 we would use Copyprofile, configure items in the captured image, and that worked great. Since Copyprofile is a no-go with Win10 it seems, what is the best approach going forward? WICD? Don’t configure in captured image, but apply during deployment TS?
A: Microsoft is moving towards less IT configuration and more personal configuration by end-users. This makes it less worthwhile doing customizations but when you need to do them you have a couple of options. Do the in the deployment TS or use GPOs. Since in-place upgrade is going to be the way between versions and you can’t customize the install.wim file moving them elsewhere will be needed.

Q: Is it better to remove Appx packages from win 10 via a powershell script during OS deployment, or via applocker (so that they never get installed for the users) anyone have experience/comparison to both
A: Removing Appx packages can only be done with PowerShell. Applocker will not remove them only block them from being used. If you want to scale down on the apps make sure to remove AppX packages and the AppX provisioned packages.

Q: Why don’t use ConfigMgr for reference images?
A: Until very recently that was not an option due to the fact that ConfigMgr will install the client as part of deployment and we want to avoid that. We still prefer MDT due to the fact its smaller, needs to infrastructure to work, its much faster and you also get a profile that can be customized to some extent.

Q: In your experience, has anyone needed hardware upgrades to go from win7 to win10? Or are real-world HW requirements the same?
A: This is a split question. If a model is supported no they won’t need an upgrade x64 requirements for Windows 7 and 10 are the same. Windows 10 will even be kinder to your hardware giving you more bang for your buck.

The thing to lock out for is of course that old models might not be vendor supported for Windows 10 and a lot of older models does not support full UEFI. Thus, for those models you won’t be able to turn on features like, Device guard and Credential guard.

Q: Would MDT Version: 6.2.5019.0 work with Win 1607, if I was to start testing deployment?
A: No, you will need a newer ADK and that is not supported with the old versions of MDT. The newer version of MDT also contains a massive amount of bugfixes so make sure to upgrade MDT instead.

Q: Does CM1610 with MDT 8443 support ADK 1511? I ask because we have to use 802.1x port authentication in our boot images and that is broken in ADK 1607.
A: Kind of, 1606 does support ADK1511 and I have not seen statements that 1610 requires ADK1607 to work. Its more a question on which OS you want to deploy. Check the link for support statement on ADK and ConfigMgr from the Microsoft Team.

Q: What was the package to add for Win 10 v1607 in MDT to fix WU issue?
A: Make sure to add the latest CU for November that is KB 3200970 together with servicing stack update KB3199986

Q: Adding the CU via a Package, but it still appears to download it from WU. Also, tried to add it the image via DISM, but same result. Any suggestions on how to prevent it from downloading?
A: This is a known issue that can be read from the KB article. To avoid it install them as applications before the first Windows Update step runs.

Q: KB3197954 is superseded so just add in the next Cumulative Update for Windows 10 Version 1607? do the next one have a working WU agent or do a first need to install this one?
A: No, all CUs contains all the previous month’s patches so the latest one will cover everything you need.

Q: What could we expect roadmap wise, with MDT and SCCM, compared to roadmap of Win 10? Will MDT / SCCM keep up?
A: Both ConfigMgr and MDT is dedicated to staying current with Windows 10. This means that MDT will be updates when needed for deployment and ConfigMgr will get continues releases to add features and fix bugs. Just this year we have seen 3 production releases of ConfigMgr (1602, 1606 and 1610)

Q: What’s the top benefits using MDT+ConfigMgr together?
A: MDT adds about 280 built-in features through scripts. You may of course build that yourself using native ConfigMgr but I have more fun things to do with my time. And if you build them yourself you will have to support them. MDT on the other hand is supported by Microsoft.

Q: Do you recommend custom Windows10 images and what is your go to image creation tool?
A: Always use MDT for reference image creation. I recommend using custom images for bare metal deployment so you can add in things your end users will need, like Visual C++ runtimes and .Net Framework. For upgrades, custom images are not supported so you will need both.

Q: When creating a W10 ref image, would you recommend applying the latest CU offline or online?
A: Both work but if you want to save time do them online otherwise it will redownload the patch to apply certain things again.

Q: Deploying with 1607 ADK working with win 7 deployment?
A: There is one big issue using the ADK 1607. Driver injection on Windows 7 with ADK1607 will fail when running on SSD drives. Using a ADK1511 boot image will solve that issue.


Hope this has helped you out with your deployments


Windows 10 – anniversary update

The new version of Windows 10 has been released. Since the build was completed during the month of July it has been named 1607 and has a build version number of 14393. The new version can be deployed using the current version of MDT but needs an upgraded ADK to fully work. The new ADK can be downloaded from here

Don’t forget to rebuild your reference images to include C++ runtimes and other needed application frameworks for your organization.

If you want to know more about what’s new in ADK check you Johan Arwidmarks blog about that here

I have not found any new releases of the ADMX templates but the current ones can be used from and installed OS with 1607. You will find them under C:\Windows\PolicyDefinitions.

Happy deploying!


Enable credential guard in configmgr

While working with at customer last we it was decided they wanted Credential Guard. Which in it self is a good thing. The problem was that they wanted this enabled as part of the Configuration Manager OSD.

Now normally automating things during ConfigMgr OSD isn’t to difficult however ConfigMgr has a problem with things that require double reboots. Since Hyper-V is a prerequisite for Credential Guard and Hyper-V requires a double reboot this poses a problem.

This might be solved by Microsoft in the future but for now you will have to employ a bit of a workaround. This consists of a couple of things, one is setting it up so you have a reboot not monitored by the task sequence and the other is installing the required roles and lastly you will also need to input the relevant registry values to enable the features.

Step 1 – Adding a reboot outside of the task sequence

This is something you should probably do anyway and it is documented in several blogpost before this one.

You will need to set a custom task sequence variable called SMSTSPostAction and set that to “Shutdown /r /t 30” this will cause a reboot 30 seconds after sequence thinks its done.


Step 2 – Creating the package

Download the script from here and put it in a folder on your CMSources share. Create a new package and a program and define the following as command line for running it: “PowerShell.exe –ExecutionPolicy ByPass –file “Enabled-CredentialGuard.ps1”

Don’t forget to enabled “Allow this program to be installed from the Install Package task sequence without being deployed”

Step 3 – Customize the task sequence

Lastly we customize the sequence to run this specific package at specific point in the sequence. The rule here is that it needs to be run after any other steps that can cause a reboot as the script will install and configure everything but the reboot should happen outside of the sequence as we configured it during step 1.

So for this customer that happens just before status is set to 5 as you can se in the picture below.


The last customization is to set an option on this to check for a task sequence variable. You should check for isUEFI equals true. This is to make this only applied to UEFI based machines as it will not work on legacy bios. If you want to you can add steps to check for Secureboot or other pre reqs.


The script – raw

Created:     2016-04-02
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

Function Import-SMSTSENV{
        $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
        Write-Output "$ScriptName - tsenv is $tsenv "
        $MDTIntegration = "YES"
        #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
        Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
        Write-Output "$ScriptName - Running in standalonemode"
        $MDTIntegration = "NO"
    if ($MDTIntegration -eq "YES"){
        if ($tsenv.Value("LogPath") -ne "") {
          $Logpath = $tsenv.Value("LogPath")
          $LogFile = $Logpath + "\" + "$LogName.log"
        Elseif ($tsenv.Value("_SMSTSLogPath") -ne "") {
          $Logpath = $tsenv.Value("_SMSTSLogPath")
          $LogFile = $Logpath + "\" + "$LogName.log"
        $Logpath = $env:TEMP
        $LogFile = $Logpath + "\" + "$LogName.log"
Function Start-Logging{
    start-transcript -path $LogFile -Force
Function Stop-Logging{


# Set Vars

$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$SettingsFile = $SCRIPTDIR + "\" + $SettingsName
$LANG = (Get-Culture).Name
$OSV = $Null


#Try to Import SMSTSEnv


#Start Transcript Logging
. Start-Logging


#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - SettingsFile: $SettingsFile"
Write-Output "$ScriptName - Current Culture: $LANG"
Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration"
Write-Output "$ScriptName - Log: $LogFile"


#Enable Hyper-V
If ([environment]::Is64BitOperatingSystem -eq $True) {
  $InstallerName = "C:\Windows\sysnative\dism.exe"
Else {
  $InstallerName = "C:\Windows\system32\dism.exe"
$Arg = "/online /enable-feature /featurename:Microsoft-Hyper-V-Hypervisor /all /LimitAccess /Norestart"
Write-Output "About to run $InstallerName with arguments $Arg"
$Result = Start-Process -FilePath $InstallerName -ArgumentList $Arg -NoNewWindow -Wait -PassThru
Write-Output "Finsihed installing Hyper-V-Hypervisor with exitcode $($Result.ExitCode)"

$Arg = "/online /enable-feature /featurename:IsolatedUserMode /LimitAccess /Norestart"
Write-Output "About to run $InstallerName with arguments $Arg"
$Result = Start-Process -FilePath $InstallerName -ArgumentList $Arg -NoNewWindow -Wait -PassThru
Write-Output "Finsihed installing IsolatedUserMode with exitcode $($Result.ExitCode)"

$Arg = "/online /disable-feature /featurename:Microsoft-Hyper-V-Tools-All /Norestart"
Write-Output "About to run $InstallerName with arguments $Arg"
$Result = Start-Process -FilePath $InstallerName -ArgumentList $Arg -NoNewWindow -Wait -PassThru
Write-Output "Finsihed removing Hyper-V Tools with exitcode $($Result.ExitCode)"

#Enable Credential Guard
$Path = "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard"
New-Item -Path $Path -ItemType Directory -Force -ErrorAction SilentlyContinue
New-ItemProperty -Path $Path -Name EnableVirtualizationBasedSecurity -PropertyType 4 -Value 1 -ErrorAction SilentlyContinue
New-ItemProperty -Path $Path -Name RequirePlatformSecurityFeatures -PropertyType 4 -Value 1 -ErrorAction SilentlyContinue
New-ItemProperty -Path $Path -Name HypervisorEnforcedCodeIntegrity -PropertyType 4 -Value 0 -ErrorAction SilentlyContinue

New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name LsaCfgFlags -PropertyType 4 -Value 1 -ErrorAction SilentlyContinue


#Stop Transcript Logging
. Stop-Logging

creating a outlook signature with logo

The other week I was working at a customer and the requested that we rebuild the way they create their Outlook signature from the old word document template. And as we can use PowerShell for everything today that’s where we went. The problem with doing it this way is that the logo image was residing on a file share in their internal environment. This means as soon as the email is sent the image is not attached and the receiving end could not the their logo.

So to fix this there is a small registry value you can set to make sure outlook always includes images. You can also find the complete script here.

First off we need to create a folder structure cause the script has another feature which they requested. So create a folder and inside that folder place the script, your logo image file and create another folder inside named Pictures.

Like this:Folder

Open up the script and at the top of the script change two things, first change the name of the logo file to whatever your file is named and change the name of the signature to something fitting your environment. The name you type in here is the one that will show up if select a different signature in Outlook.

Next Check the bottom of the script there are two sections one being the registry settings to make sure to include the image and the other is a value to defined if the signature should be used by default. If you wish to use this just uncomment the lines creating each of the registry values.

Now just run the script!
That’s it to creating the signature. If you want to customize the look of the signature its a common html creation so pretty much anything is possible.

It should give you a signature looking something like this.


So how does it work? Well we start by getting the username of the current user and then do an AD query for that user and get the above values. This means that whatever is in Active Directory will be in the signature creating a streamlined and unified look for every person in your organization.

Once that is done it will get the logo picture and insert that as well. Next comes the nice extra feature with the Picture folder you created. All images you add in here will be added to the bottom of the signature. So now the question is why would you want that? Well a number of customers I work with like to add a banner at the end during certain times of the year or when they want to push a certain product or happening. Now it can be centrally controlled and all users will get it.

Just don’t forget to remove old pictures in the folder.

So to finish up, deployment!
To accomplish this I create a GPO than runs a login script. If you don’t want to do that you can always do a scheduled task that checks a certain network folder and runs the script or any other preferred solution.

Link to the script is here

Hope this helps and 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



Merge WIM into one – the space saver

I have gotten this question a couple of times “can i have two operating systems to choose from in one task sequence”. Well the correct answer to that is yes, but it takes up alot of unecessary space and if you are using ConfigMgr and need to download 2 wims instead of 1 well that adds alot of time.

What I would instead recommend is merging two Wim files into one, this will save alot of space and still give you the option to use different ref images in the same task sequence.

So how is this done?

First off you need to create two ref images. The most common senario for this is you have one with Office preinstalled and one without Office preinstalled. So if we look at how that looks you will get something like this:


In this case I am using Windows 10 ref images but this works just as well with Windows Vista, 7, 8 and 8.1 (all Wim based OSes).

So as you can see they are around 4-5GB in size. The next step now is to merge them. To help with this i have a small script that you can use.

What the script does is it takes one wim and mounts it. Then it applies the mounted wim into the other wim so you get two indexes and next it cleans up the mounted directory and finally displays the different indexes in the merged wim file.

You can download the script here:

When that is complete you get something looking like this.


As you can see the image is now a bit bigger but it has not doubled in size. This is due to the fact that when the wims are merged it will throw away all duplicate files to keep the file size down.

This method is the same method Microsoft have used when they have created Windows Server medias in the past containing core and gui versions on the same media.

The next step is to import this into whatever solution you are using (MDT/SCCM).

In this instance I have used MDT and it looks similar in SCCM but there are a couple of differentes. If you are unsure, drop me an email or pm and I can help you out.

So, import Operating system, custom image and point to the wim created erlier. When its done it looks something like this


If we look at the preferences for these two operating systems you can see that they both use the same file in the background but different indexes.


Now you can add another install operating system step and select different citeras to run the different steps. For instance, different blocks in CustomSettings.ini, some setting in the MDT database or add a new setting to the MDT database and use that. Use webservices and if the computer is this OU or AD group it should have office and if not it shouldn’t. The possibilities to create rules are as always limitless.

Happy deploying!