Flipping the switch: How to enable Co-management in SCCM Current Branch (System Center Configuration Manager)

Introduction

Co-management! It was announced last year at Ignite in Orlando and it’s being pushed heavily these days by Microsoft. For those who don’t know the ups and downs, co-management is basically (for those using ConfigMgr already) managing computers with both a Configuration Manager client and Intune MDM.

There are different possibilities to achieve co-management. It may sound complicated, but it’s not. I will walk you through the few steps required, as well as cover the precise prerequisites and how to troubleshoot issues if any. Note: This is precisely how I have done in a production environment. Curious? Read on 🙂

Read more…

Upgrading Configuration Manager Current Branch to version 1802 (A real example from a real production environment)

Introduction

I know. There are tons of similar post explaining how to upgrade Configuration Manager Current Branch to the latest version, but that’s not a valid reason not to do another one (:D). Also, mine is exactly how I did it in our production environment, from beginning till end, and not in a lab where you usually (I do) almost blindfolded click next and accept everything, without any precautions.

This is a stand-alone primary site in an enterprise environment of a midsize company in Denmark, running on Windows Server 2016 (I most recently did an in place upgrade of the OS from 2012. Another blog post incoming soon), and for your inspiration, this is the exact steps I went through. Curious? Read on 🙂

Read more…

Create required registry key for Intel vulnerability (#Meltdown #ADV180002) using Compliance Settings in SCCM)

Introduction

Unless you have been hiding under a rock since Christmas, you should have heard about the new CPU vulnerability found in Intel and AMD chips: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/ADV180002

Long story short, following this vulnerability Microsoft instantly made changes to their OS, requiring all AV (Antivirus) products to be compatible with these new changes.

Everything in details in this link: https://support.microsoft.com/da-dk/help/4072699 

What the article also mentions is that any Windows OS won’t be offered the January Security Updates (and any subsequent) until a very specific registry key is present on the systems. This is seen, when computers in your environment doesn’t request the update when you expect it to, and when compliance reports in ConfigMgr tells you that the update show up as Not Required when you know it is.

Most AV products by this time do create the registry key already, but what if you do not use any AV (for whatever reason that may be), and what if you want to make sure the registry key is there already and always is. Use Compliance Settings in ConfigMgr. Usually for on-prem domain joined computers, I would stick to Group Policies, but for this in particular, Compliance Settings in ConfigMgr does a way better job in regards to remediation and reporting of compliance.

Configuration

  • Create a new Configuration Item in ConfigMgr following these snippets (Assets and Compliance tab)

  • Add the newly created Configuration Item to Configuration Baseline, and deploy the baseline to selected collections.

Finally

Go to the Monitoring tab of the ConfigMgr console and expand Reporting -> Reports -> Compliance and Settings Management and find the report: Summary compliance by configuration baseline and lean back and watch how your clients are reporting back compliance. (Might take a while depending on your Client Policy Settings)

 

Updating Office 365 ProPlus. A custom alternative (Using Powershell App Deployment Toolkit and SCCM)

Introduction

First off, this is probably not for everyone. ConfigMgr and WSUS can deploy updates to the O365 ProPlus client just fine and most needs are probably satisfied this way. However, if you are interested in more visibility before, during and after deploying O365 updates to your users – read on!

After updating ConfigMgr to 1706 (from 1610 and 1702) something changed in the behavior of installing O365 ProPlus updates. Previously, in 1610 and 1702, the behavior was actually quite transparent for the end user: A restart flag is set and the update is installed after the computer restarts. This actually meant that you could deploy any update to o365 ProPlus and not worry about notifying your users about anything but the coming restart (which is somewhat similar to the behavior of standard software updates for Windows)

Coming ConfigMgr 1706, this changed dramatically to in-app notifications as well as forced shutdown of apps (and potential loss of unsaved work) if the right circumstances was in place. Also, when the apps are shut down, nothing is being displayed to notify the user about the progress, so most users will re-open the Office apps right away creating even more problems.

The Microsoft Docs article for the change in behavior is outlined right here: https://docs.microsoft.com/en-us/sccm/sum/deploy-use/manage-office-365-proplus-updates#restart-behavior-and-client-notifications-for-office-365-updates

I urge anyone managing O365 updates with ConfigMgr to give it a read and take notes of all the possible outcomes when deploying O365 updates this way. To quote the important ones (note all the maybe’s, which makes the experience really inconsistent):

  • A pop-up notification might not display until the user clicks the icon in the notification area. In addition, if the notification area has minimal space, the notification icon might not be visible unless the user opens or expands the notification area
  • If the deadline is in the past or configured to start as soon as possible, running Office apps might be forced to close without notifications (they do – yay)
  • The in-app notification bar does not display on an Office app that is running before the update is downloaded. After the update is downloaded, the in-app notification displays only for newly opened apps (the yellow in-app bar is inconsistent. Sometimes it shows, sometimes it doesn’t. Reopening apps or not)

So, enough with the ranting. Above is the facts about the poor user experience when running ConfigMgr 1706. Below will be how I used something totally different to create visibility for our users.

Powershell App Deployment Toolkit!

We all know the infamous Powershell App Deployment Toolkit: http://psappdeploytoolkit.com/. (And if you don’t, that’s another day and another blog post 🙂

Below is exactly how (and along the lines, why) I chose to leverage the use of the Powershell Deployment Toolkit and the ODT to deploy O365 updates in my organization.

Configuration

Create the Office Deployment Tool .xml file (Update.xml)

The ODT relies on a .xml file. That is whether you want to update or downgrade your Office 365 ProPlus installation. In this scenario I want to update, and for this I can specify exactly what build I want to update to. If you don’t specify a version, you will be updated to the latest build in your channel. A lot of the content in the .xml is optional, and something you also can manage through ConfigMgr or GPOs.

This is exactly the .xml file I’m using to update my Monthly Channel (previously called Current Channel) clients to the latest build. I manage the channel through GPOs, which is why you don’t see the channel being set in my .xml.

<Configuration>
  <Add OfficeClientEdition="32" Version="16.0.8730.2127" OfficeMgmtCOM="True" >
    <Product ID="O365ProPlusRetail">
      <Language ID="en-us" />
      <ExcludeApp ID="Groove" />
      <ExcludeApp ID="InfoPath" />
      <ExcludeApp ID="Publisher" />
      <ExcludeApp ID="SharePointDesigner" />
    </Product>
  </Add>
  <Logging Level="Standard" Path="C:\Windows\Temp" />
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="AUTOACTIVATE" Value="1" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />  
</Configuration>

Create the folder structure

This is optional and just an illustration of how I do it. I have a complete folder structure in my source file library equal to something similar to this:

8431.2107 and 8730.2127 are build numbers and is respectively version 1708 and 1711. Complete list of all the builds numbers and release dates for Monthly and Semi-Annual channel, look here!

Inside each build number, I have the Powershell Deployment Toolkit:

Inside the Files folder, I put my newly created Update.xml along side the Setup.exe from the ODT and a Update.bat file (which is what we will have the PS Deployment Toolkit running) containing following:

@echo off
“%~dp0setup.exe” /configure “%~dp0Update.xml”

I’m using a batch file to wrap the installation into, for the diversity and simplicity. If needed I can quickly edit the batch file, update DPs and move on (opposed to edit the PowerShell script)

Roll-back and downgrade

If needed, you can have the ODT (Setup.exe) to downgrade the version of Office 365 ProPlus as well. This is also done configuring the proper settings in an .xml file.

Below is my .xml file used to downgrade Office 365 ProPlus. Notice ForceDowngrade=”True” which is required if you are moving backwards (a SaaS like this, is meant to move forward 🙂 Again, take a look at this page for knowledge about the different versions/builds for your channel: here!

<Configuration>
  <Add OfficeClientEdition="32" Version="16.0.8431.2107" OfficeMgmtCOM="True" ForceDowngrade="True">
    <Product ID="O365ProPlusRetail">
      <Language ID="en-us" />
      <ExcludeApp ID="Groove" />
      <ExcludeApp ID="InfoPath" />
      <ExcludeApp ID="Publisher" />
      <ExcludeApp ID="SharePointDesigner" />
    </Product>
  </Add>
  <Logging Level="Standard" Path="C:\Windows\Temp" />
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="AUTOACTIVATE" Value="1" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />  
</Configuration>

This I wrap into a Downgrade.bat as well inside the Files folder of the Powershell Deployment Toolkit. (In a separate folder. For a separate package in ConfigMgr.)

@echo off
“%~dp0setup.exe” /configure “%~dp0Downgrade.xml”

The above configurations is made to actually download the differences in bits directly from the Office CDN. This is also something to consider if using this method. However, you can specify SourcePath=”” to let the installation grab the bits from a local source if desired. Microsoft has specified the download sizes in this post here!

<Add OfficeClientEdition="32" OfficeMgmtCOM="True" SourcePath="\\Server\Share\Monthly Channel" >

Deployment

With all of above in place, you will be ready for deployment with ConfigMgr. Note that I assume that you know your way around the Powershell Deployment Toolkit.

To target the update of Office to the proper computers, I use collections. ConfigMgr is able to inventory a lot of useful information regarding the Office 365 ProPlus client which includes the current version, channel etc:

This query example will give you all computers that: Has Office 365 ProPlus installed, runs on Current Channel set through GPO and is NOT already on the latest 1711 build. (This should probably be altered to fit your needs and environment, depending on various factors)

select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS_64 on SMS_G_System_ADD_REMOVE_PROGRAMS_64.ResourceID = SMS_R_System.ResourceId inner join SMS_G_System_OFFICE365PROPLUSCONFIGURATIONS on SMS_G_System_OFFICE365PROPLUSCONFIGURATIONS.ResourceID = SMS_R_System.ResourceId where SMS_G_System_ADD_REMOVE_PROGRAMS_64.DisplayName like "Microsoft Office 365 ProPlus%" and SMS_G_System_OFFICE365PROPLUSCONFIGURATIONS.GPOChannel = "Current" and SMS_R_System.NetbiosName not in (select SMS_R_System.NetbiosName from  SMS_R_System inner join SMS_G_System_OFFICE365PROPLUSCONFIGURATIONS on SMS_G_System_OFFICE365PROPLUSCONFIGURATIONS.ResourceID = SMS_R_System.ResourceId where SMS_G_System_OFFICE365PROPLUSCONFIGURATIONS.VersionToReport = "16.0.8730.2127")

With this in place, you will have isolated the computers in need of being a target for your Office 365 ProPlus update.

Finally

Now there’s only a few steps left, but I assume you already know how to:

  • Customize your Powershell Deployment Toolkit to your needs
    • Close the Office apps, and keep them closed (prevent users from starting any, until the installation is done)
    • Keep the user notified during the entire process through custom dialogs
    • Show a friendly restart dialog, prompting the user to restart within allotted time
  • Create a package in ConfigMgr, distribute to your favorite DPs
  • Test the deployment
  • Deploy to your users
  • Be happy about the process being a lot smoother in regards to user friendliness.

GIF of everything in action: Installation running, user trying to open Word and the dialogs that follow.

Detect vulnerability in TPM (ADV170012) using ConfigMgr Compliance Settings

Introduction

Coming Patch Tuesday this month, Microsoft revealed a whooping vulnerability in some infineon TPM chips; ADV170012

In the above article, Microsoft gives us some insight on the vulnerability itself, as well as how to detect and counter the vulnerability.

As how to detect the vulnerability, they released a patch which writes an entry to the event log and highlights the vulnerability in TPM.msc.

They also released a Powershell script, which they in turn – unfortunately – don’t go into much details about. They tells us to use PSremoting to query multiple computers and nothing else.

So, how about using ConfigMgr to detect whether our computers are vulnerable or not? Compliance Settings to the rescue!

I rewrote their script to instead return $true or $false, and make it usable to detect compliance or non-compliance.

So, following is my edition of the script, and how to setup the CI in ConfigMgr

Configuration

<#

.DESCRIPTION
    Detect if Infineon TPM is vulnerable to Microsoft ADV170012 through Compliance Settings in ConfigMgr

.NOTES
    FileName:    CIDetectTPM.ps1
    Author:      Martin Bengtsson
    Created:     14-10-2017
   
#>

$IfxManufacturerIdInt = 0x49465800 # 'IFX'
		
		function IsInfineonFirmwareVersionAffected ($FirmwareVersion)
		{
			$FirmwareMajor = $FirmwareVersion[0]
			$FirmwareMinor = $FirmwareVersion[1]
			switch ($FirmwareMajor)
			{
				4 { return $FirmwareMinor -le 33 -or ($FirmwareMinor -ge 40 -and $FirmwareMinor -le 42) }
				5 { return $FirmwareMinor -le 61 }
				6 { return $FirmwareMinor -le 42 }
				7 { return $FirmwareMinor -le 61 }
				133 { return $FirmwareMinor -le 32 }
				default { return $False }
			}
		}
		
		function IsInfineonFirmwareVersionSusceptible ($FirmwareMajor)
		{
			switch ($FirmwareMajor)
			{
				4 { return $True }
				5 { return $True }
				6 { return $True }
				7 { return $True }
				133 { return $True }
				default { return $False }
			}
		}
		
		$Tpm = Get-Tpm
		$ManufacturerIdInt = $Tpm.ManufacturerId
		$FirmwareVersion = $Tpm.ManufacturerVersion -split "\."
				
		if (!$Tpm)
		{
			#No TPM found on this system, so the issue does not apply here."
            Return $True
		}
		else
		{
			if ($ManufacturerIdInt -ne $IfxManufacturerIdInt)
			{
				#This non-Infineon TPM is not affected by the issue."
                Return $True
			}
			else
			{
				if ($FirmwareVersion.Length -lt 2)
				{
					#Could not get TPM firmware version from this TPM."
                    Return $True
				}
				else
				{
					if (IsInfineonFirmwareVersionSusceptible($FirmwareVersion[0]))
					{
						if (IsInfineonFirmwareVersionAffected($FirmwareVersion))
						{
							#This Infineon firmware version {0}.{1} TPM is not safe. Please update your firmware." -f [int]$FirmwareVersion[0], [int]$FirmwareVersion[1])
                            Return $False
						}
						else
						{
							#This Infineon firmware version {0}.{1} TPM is safe." -f [int]$FirmwareVersion[0], [int]$FirmwareVersion[1])
                            Return $True
						}
					}
					else
					{
						#This Infineon firmware version {0}.{1} TPM is safe." -f [int]$FirmwareVersion[0], [int]$FirmwareVersion[1])
                        Return $True
					}
				}
			}
		}
  • Create a new CI. Give it a name and enable it to run on all Windows Desktops and Servers (Custom)

  • At the Specify settings for this OS page, click New

  • In the Create Setting page, select Script and Boolean. Insert my script from above in Edit Script

  • In the Create Rule page, select the newly created CI

  • Add the completed Configuration Item to a Configuration Baseline and deploy to selected collections

Summary

  • Taking a closer look directly on the client on the Configurations tab of the ConfigMgr client, you will either notice a compliant or non-compliant state

  • For a better summary of compliance, I personally like to create collections. Go to the deployment of the Configuration Baseline, and right click. Below is your options to create additional collections

  • The net result is a set of collections which memberships clearly tells the compliance state of the TPM vulnerability

Download my CI and baseline here: https://www.imab.dk/mab/CB_TPMVulnerability_Status.zip

Enjoy 😎

 

Switch Office 365 ProPlus update channel using the Software Center in SCCM (System Center Configuration Manager)

Introduction

Following is a post on how I let (some) of our users decide whether they want to roll on the Current Channel (now called Monthly) or the Deferral Channel (Now called Semi-Annual and Broad) for Office 365 ProPlus.

According to numerous blogs on the www, there are several ways of doing this; modifying registry, GPO, reinstalling Office or to rerun setup.exe from the Office Deployment Tool (ODT).

I’ve chosen to go with the last option, and modify the channel through setup.exe coming from ODT. (I spent some time on GPO and modifying the registry without the expected results. However using setup.exe gives you visibility and a method that yields the results right away)

Configuration

  • Go ahead and download Microsoft Deployment Tool (ODT) if you haven’t already. Link: Download Office 2016 Deployment Tool
  • Create two new .xml files containing following content (one for each channel switch)

Semi-Annual channel (also called Deferred or broad):

<Configuration> 

	<Updates Channel="Deferred" /> 

</Configuration>

Monthly channel (also called current):

<Configuration> 

	<Updates Channel="Monthly" /> 

</Configuration>
  • Put the .xml files in folder next to setup.exe from the Microsoft Deployment Tool (ODT)
  • Create two .bat files containing following content (one for each channel switch)
    • I’m deleting the current regkeys responsible for setting the channel prior to making the actual switch. This is due to some weirdness I’ve been seeing where the values are not properly updated.

SetDeferred.bat:

@echo off
reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration /v CDNBaseUrl /f
reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration /v UpdateChannel /f
"%~dp0setup.exe" /configure "Deferred.xml"
"%CommonProgramFiles%\microsoft shared\ClickToRun\OfficeC2RClient.exe" /update user

SetMonthly.bat:

@echo off
reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration /v CDNBaseUrl /f
reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration /v UpdateChannel /f
"%~dp0setup.exe" /configure "Monthly.xml"
"%CommonProgramFiles%\microsoft shared\ClickToRun\OfficeC2RClient.exe" /update user
  • Put the two .bat files into the same folder and copy the content to your content library used in ConfigMgr (Whereever that may be. This is pretty standard, so I’m not going into details here)
  • Create two new Applications in ConfigMgr with a Deployment Type set to Script Installer. Below the snippets from the Create New Application process.

  • Set the previously created .bat files as the installation program (SetDeferred.bat)

  • Detection rules for the applications will be the corresponding registry keys. The value of the below registry key is changing upon switching channels.

Monthly Channel: http://officecdn.microsoft.com/pr/492350f6-3a01-4f97-b9c0-c7c6ddf67d60

Deferred Channel: http://officecdn.microsoft.com/pr/7ffbc6bf-bc32-4f92-8982-f9dd17fd3114

  • Distribute the content of the newly created applications to your preferred distribution points (groups), and deploy the applications.

Summary

Running the applications will result in either an upgrade or downgrade of Office 365 ProPlus.  This should be followed by a series of windows which will take you through the process for the new channel that you have switched to.

This is something I have deployed internally in the IT department, enabling them to easily switch between the channels.

Enjoy! 😎

References:
https://support.microsoft.com/en-us/help/3185078/how-to-switch-from-deferred-channel-to-current-channel-for-the-office
https://blogs.technet.microsoft.com/odsupport/2017/05/10/how-to-switch-channels-for-office-2016-proplus/

Converting from BIOS to UEFI with Powershell (During OSD using SCCM on Lenovo laptops)

Following my previous post, this is an quick example on how to use my Powershell script to convert from BIOS to UEFI in a bare metal scenario. (Again, only Lenovo laptops is working with this script)

Most of the magic lies within the Task Sequence itself, so I will break it down in pieces:

  • Create a group in your Task Sequence called “Prepare Computer (BIOS)” with the condition _SMSTSBootUEFI not equals true (This will make sure the content of the group only runs if UEFI is not enabled already)

  • Next step, format the disk with following settings (Step: Format and Partition Disk (BIOS))
    • Disk type: Standard (MBR)
    • Partition type: Primary
    • 100% remaining disk
    • File system: NTFS

  • Next step, create a new group called Config Lenovo BIOS with following condition: SELECT * FROM Win32_BIOS WHERE Manufacturer = “Lenovo” (This will make sure the step only runs on a Lenovo computer)

  • Next step, run my Powershell script directly from a package like shown below. The parameter -EnableSecureBoot will also enforce UEFI to be enabled.

  • Next step, format the disk with following settings (Step: Format and Partition Disk (BIOS to UEFI))
    • Disk type: GPT
    • Partition type: Primary
    • Size: 600Mb
    • File System: FAT32
    • Variable: TSUEFIDrive
  • Add another partition:
    • Partition type: Primary
    • Size: 100% of remaining space
    • File system: NTFS
    • Variable: None

  • Next step, one final reboot to the boot image currently assigned to this task sequence. When the task sequence returns from the reboot, the Lenovo BIOS will be set to SecureBoot AND UEFI and Windows will continue installing.

Ultimately, you can have 2 steps to take care of when the computer is coming with either BIOS setting or UEFI, and act accordingly. Se below snippet for inspiration.

Enjoy! 🙂

 

Manage Lenovo BIOS with Powershell (During OSD with SCCM)

Update: Post and script moved to https://www.imab.dk/lenovo-bios-configurator/

I have no idea if this is something that has already been created out there, but I figured I’d do it anyway. Mostly because Powershell, I need the practice and I needed the ability to easily modify the BIOS in our Lenovo environment.

The script is inspired by the original VB script from Lenovo, which roughly does the same as my Powershell script. Lenovos script and documentation can be reached from this link (https://support.lenovo.com/dk/en/solutions/ht100612). However, it’s VB and it gives me shivers, so Powershell to the rescue.

The script is still work in progress, as it doesn’t hold all the abilities as the original Lenovo script, but I prioritized the ability to turn on/off following: Virtualization, SecureBoot, PrebootUSB-C/Thunderbolt and TPM.

You basically just run the script with parameters. Example: LenovoBIOSManagement.ps1 -EnableTPM -EnableSecureBoot -DisableVirtualization -Restart

An example from the use in my recent Windows 10 Task Sequence. The step is run prior to formatting the disk in WinPE. I have a condition on the step, to only run if a Lenovo laptop.

Enable Preboot Thunderbolt is separated as a single step, as it’s currently only the most recent Lenovo laptops which has this ability: T470s, X1 Yoga 2nd generation etc., and therefore has a condition to only run if such model is being deployed.

I’d appreciate any feedback. I’m by no means any Powershell champ, but I’m still learning – and willing to learn 🙂

Thanks!

Update: Post and script moved to https://www.imab.dk/lenovo-bios-configurator/

Configuration Manager collection based on Client Creation Date (Dates in WMI)

I just had a very specific scenario, requiring me to target all new mobile devices (post a specific date) with a different set of compliance settings, than the rest of the devices.

In that case you can separate newly created devices in their own collection, based off their creation date.

The time of when a device is created is stored in the database, and the data can be queried through WMI using WQL.

A date formatted in WMI is using following syntax: yyyymmddHHMMSS.xxxxxx±UUU and can look like this:

20170819071629.492270+120

So, if you want all devices created post July 1 2017, your query have to look like this:

The syntax for dates in WMI in details: https://technet.microsoft.com/en-us/library/ee198928.aspx?f=255&MSPPError=-2147217396

Powershell: Enable virtualization and Credential Guard in an instant (Lenovo laptops)

Windows 10 Credential Guard is currently another hot topic considering cyber security. Credential Guard is a new feature in Windows 10 (Enterprise and Education edition) that helps to protect your credentials on a machine from threats such as pass the hash.

To be able to enable Credential Guard in Windows, you need to have virtualization enabled on the CPU in the BIOS. Virtualization is rarely enabled by default, and as such you will need to enable it manually (F1, enter BIOS, modify the setting) or better yet, find a solution to do so remotely and automatically.

I have created following script in Powershell, that initially enables virtualization in the BIOS (Note: We only use Lenovo laptops, hence this is made for Lenovo laptops only) and then apply the registry-keys to enable Credential Guard. All steps are logged into c:\Windows\EnableCredentialGuard.log

The script can be targeted to the proper Windows 10 versions through SCCM collections (I this example I only target W10 1607 and 1703, as these Windows 10 versions no longer require the Isolated User Mode feature when enabling Credential Guard, as it’s now embedded into the Hypervisor)

When deploying powershell script from SCCM, remember to create the program with a command line like this: powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\CredentialGuard\Enable-VirtualizationCredentialGuard.ps1

<#
.SYNOPSIS
    Enable virtualization in Lenovo Bios and enable Credential Guard in Windows 10
.DESCRIPTION
    This script will only run on Lenovo computers. If run on Lenovo computer, the script will check if virtualization is enabled in BIOS. 
    If not, virtualization will be enabled in the process of enabling CredentialGuard.
    Also appends actions to logfile: EnableCredentialGuard.log
 
.NOTES
    FileName:    Enable-VirtualizationCredentialGuard.ps1
    Author:      Martin Bengtsson
    Created:     19-07-2017
#>

$Logfile = "C:\Windows\EnableCredentialGuard.log"

#Create LogWrite function
Function LogWrite
{
   Param ([string]$Logstring)

   Add-Content $Logfile -Value $Logstring
}

#Get computermanufacturer
$Lenovo = Get-WmiObject Win32_ComputerSystemProduct | Select-Object Vendor

#If not a Lenovo laptop, write to log and exit script
If ($Lenovo.Vendor -ne "Lenovo"){
    
    LogWrite "Not a Lenovo laptop - exiting script"
    Write-Warning -Message "Not a Lenovo laptop - exiting script" ; exit 1
}

Else {
    
    Write-Host -ForegroundColor Yellow "Collecting Lenovo_BiosSetting information" ; LogWrite "Collecting Lenovo_BiosSetting information"
    $VirtEnabled = Get-WmiObject -Class Lenovo_BiosSetting -Namespace root\WMI | Where-Object {$_.CurrentSetting -match "Virtualization*"} | Select-Object CurrentSetting

If ($VirtEnabled.CurrentSetting -eq "VirtualizationTechnology,Disable"){
    
    Write-Host -ForegroundColor Cyan "Virtualization disabled - trying to enable virtualization" ; LogWrite "Virtualization disabled - trying to enable virtualization"
    Try {
        (Get-WmiObject -Class Lenovo_SetBiosSetting -Namespace root\wmi).SetBiosSetting("VirtualizationTechnology,Enable")
        (Get-WmiObject -Class Lenovo_SaveBiosSettings -Namespace root\wmi).SaveBiosSettings()

    }
    Catch {
        Write-Host -ForegroundColor Cyan "An error occured when enabling virtualization in the BIOS" ; LogWrite "An error occured when enabling virtualization in the BIOS" ; exit 1
    }
    cls
    Write-Host -ForegroundColor Cyan "Virtualization Successfully enabled" ; LogWrite "Virtualization Successfully enabled"
    
}

#Add required registry key for Credential Guard
$RegistryKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard"
    If (-not(Test-Path -Path $RegistryKeyPath)) {
        Write-Host -ForegroundColor Yellow "Creating HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard registry key" ; LogWrite "Creating HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard registry key"
        New-Item -Path $RegistryKeyPath -ItemType Directory -Force
    }
    #Add registry key: RequirePlatformSecurityFeatures - 1 for Secure Boot only, 3 for Secure Boot and DMA Protection
    New-ItemProperty -Path $RegistryKeyPath -Name RequirePlatformSecurityFeatures -PropertyType DWORD -Value 1
    Write-Host -ForegroundColor Yellow "Successfully added RequirePlatformSecurityFeatures regkey" ; LogWrite "Successfully added RequirePlatformSecurityFeatures regkey"
    
    #Add registry key: EnableVirtualizationBasedSecurity - 1 for Enabled, 0 for Disabled
    New-ItemProperty -Path $RegistryKeyPath -Name EnableVirtualizationBasedSecurity -PropertyType DWORD -Value 1
    Write-Host -ForegroundColor Yellow "Successfully added EnableVirtualizationBasedSecurity regkey" ; LogWrite "Successfully added EnableVirtualizationBasedSecurity regkey"
    
    #Add registry key: LsaCfgFlags - 1 enables Credential Guard with UEFI lock, 2 enables Credential Guard without lock, 0 for Disabled
    New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name LsaCfgFlags -PropertyType DWORD -Value 2
    Write-Host -ForegroundColor Yellow "Successfully added LsaCfgFlags regkey" ; LogWrite "Successfully added LsaCfgFlags regkey"
    
    Write-Host -ForegroundColor Yellow "Successfully enabled Credential Guard - please reboot the computer" ; LogWrite "Successfully enabled Credential Guard - please reboot the computer"
    
}   

Snip of the logfile when everything succeeds: