PowerShell – Running a Program in Compatibility Mode

If you manually change the compatibility mode of an executable you will notice that this changes an item in the registry in the following location:

HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\

To take advantage of this from within a script:

$wDir = $PSScriptRoot
New-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\" -PropertyType String -Name "$wDir\[Program].exe" -Value "~ WIN7RTM" -Force
Start-Process "$wDir\[Program].exe" -ArgumentList @( "-i", "silent") -Wait
Remove-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\" -Name "$wDir\[Program].exe"

This can be useful to install older software.

Windows Upgrade using User Friendly Deployment/Triggering for SCCM Task Sequences

With the introduction to Windows 10 and its update cycle, if your refresh schedule is not as aggressive you are looking at having to push upgrades to your devices in order to keep them current and supported.

The real challenge comes with working around the user’s schedule to try to minimize interruptions. We opted to set up an Application that will give the user an option of kicking off the task sequence or selecting a time to Schedule the deployment.

Using a WPF form through Powershell we created a form that has a scheduled date range and time:

If they select run now the Task Sequence would kick off from the script with a block of code similar to this:

Function KickOffTS ($TSName){
 if($TSName -ne $null -and $TSName -ne ""){
 $aScript = {(Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -ClassName CCM_SoftwareDistribution -Filter "PKG_Name = `"$($TSName)`"").ADV_AdvertisementID | foreach{'Select * from CCM_Scheduler_ScheduledMessage where ScheduledMessageID like "' + $_ + '%"'} | foreach{Get-WmiObject -Query "$_" -Namespace root\ccm\policy\machine\actualconfig}|foreach{([wmiclass] "\\.\root\ccm:SMS_Client").TriggerSchedule($_.ScheduledMessageID)}}
 if((Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -ClassName CCM_SoftwareDistribution -Filter "PKG_Name = `"$($TSName)`"") -ne $null){
 $TS = (Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -ClassName CCM_SoftwareDistribution -Filter "PKG_Name = `"$($TSName)`"")
 $TSOldrrb = $TS.ADV_RepeatRunBehavior
 $TS.ADV_RepeatRunBehavior = "RerunAlways"
 $TS.put() | Out-Null
 invoke-Command $aScript
 start-sleep -Seconds 1
 $TS.ADV_RepeatRunBehavior = $TSOldrrb
 $TS.put() | Out-Null
 Else{Write-Warning "Task Sequence was not found"}
 Else{Write-Warning "Task Sequence name was not given"}
KickOffTS "[TaskSequenceName]"

If they decide to schedule the deployment a Scheduled task would kick off a condensed form of the script at the selected Scheduled time.

[email protected]"
if((Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -ClassName CCM_SoftwareDistribution -Filter \"PKG_Name = `'[TaskSequenceName]`'\")){"(Get-WmiObject -Namespace root\ccm\policy\machine\actualconfig -ClassName CCM_SoftwareDistribution -Filter \"PKG_Name = `'[TaskSequenceName]`'\").ADV_AdvertisementID | foreach{\"Select * from CCM_Scheduler_ScheduledMessage where ScheduledMessageID like `'`$_%`'\"}| foreach{Get-WmiObject -Query "`$_" -Namespace root\ccm\policy\machine\actualconfig} | foreach{([wmiclass] \"\\.\root\ccm:SMS_Client\").TriggerSchedule(`$_.ScheduledMessageID)}}
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument $aScript2 
$trigger =  New-ScheduledTaskTrigger -At $TimeScheduled -Once
$stSetting = New-ScheduledTaskSettingsSet -WakeToRun Register-ScheduledTask -Action $action -Trigger $trigger -Settings 
$stSetting -TaskName "Win10 Upgrade Task" -Description "Windows 10 Upgrade Task" -User "System" -RunLevel Highest


The task sequence you want to kick off must be deployed as required in some way to the device.

The task sequence rerun behavior must allow the task sequence to rerun. If the behavior is set to rerun if failed and the task sequence has succeeded before then your trigger action will not work. In my initial example I set the rerun behavior to “RerunAlways” then back to the previous state after the task sequence is triggered. Be careful to not cause unwanted kick offs when changing this settings.
Finally the task sequence must be allowed the scheduled time either by having a maintenance window available at that time or checking the box that allows it to run outside of a maintenance window.

After thoughts:

There were other ways to kick off task sequences using Powershell but some of these options seemed to access WMI items that were only available when the user was logged in. Not great for task sequences that you want to push at a scheduled time when the user may or may not be logged into the system. Manipulating the WMI items in the examples above gave the most consistent and reliable results.

Drivers & Where to get them.

A few different resources for drivers from different sources around the web to facilitated deployments:




SCConfigmgr.com also has a very cool scripted solution for downloading drivers which can also create driver packages automatically in SCCM I recommend checking them out because they have many other tools that can help with many different tasks:

Alternatively you can also use powershell to extract drivers from a specific model of machines and then import them to another similar model or create an SCCM package from the extracted drivers:

To export the drivers to a network share:

Export-WindowsDriver -Destination "\\[Server]\[Share]\$((Get-WmiObject -Class win32_computersystem).Model)\" -Online

There are different ways to import drivers on to an online computer I personally tend to use pnputil since this has been functional for many versions of windows:

$drivers = (Get-ChildItem -Path "\\[Server]\[Share]\$((Get-WmiObject -Class win32_computersystem).Model)\" -Filter "*.inf" -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Fullname) 
foreach($driver In $drivers){
    pnputil.exe -i -a $driver

You can also always have windows search for drivers in this location using the Device Manager > Update Driver option.