Run Scripts on Configuration Manager is one of the coolest things in a long time. I have a long list of scripts to write/blog here is the first. Update the logged on users GPOs. Then challenge with this is that the script is executed in System Context and we want to be in the users context to be be able to update the Users GPOs.
I didn’t want to copy any files so that means that that running a Powershell script in the users context is out the window as it will always flash by the console window and that is not acceptable. Solution, a PowerShell script that will create a local vbscript, yes vbscript you read it correct as we can run it completely silent without a window popping up.
It creates a Schedule Task that runs in the logged in users context which we initiate from System context to be able to trigger the update in user context.
# Script to update User GPO from System context using a Schedule Task
# Written by Jörgen Nilsson
# ccmexec.com
# Creates a local vbscript, which will run GPUpdate without displaying anything for the end user
$VBScript = @"
Set objShell = WScript.CreateObject("WScript.Shell")
Result = objShell.Run ("cmd /c echo n | gpupdate /target:user /force",0,true)
Wscript.quit(Result)
"@
$VBScript | Out-File -FilePath "$env:Windir\RunUserGPO.vbs" -Force
# Gets the logged on user
$computer = $env:COMPUTERNAME
$computerSystem = Get-WMIObject -class Win32_ComputerSystem -ComputerName $computer
$LoggedUser = $computerSystem.UserName
If ($LoggedUser -eq $null) {
Write-output "No user logged on"
Exit 1
}
# Creates and run a Schedule Task as the logged on user
$TaskName= "GPupdateUser"
$Action = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "$env:Windir\RunUserGPO.vbs /NoLogo"
$Principal = New-ScheduledTaskPrincipal "$loggedUser"
$Settings = New-ScheduledTaskSettingsSet
$Task = New-ScheduledTask -Action $Action -Principal $Principal -Settings $Settings
Register-ScheduledTask $TaskName -InputObject $Task | out-null
Start-ScheduledTask $TaskName | out-null
# Wait for Schedule task to complete
$Counter = 200 # 40 s
while ((Get-ScheduledTask -TaskName $TaskName).State -ne 'Ready' -and $Counter-- -gt 0) {
Start-Sleep -Milliseconds 200
}
if ($Counter -lt 0) {
Write-Output "Timeout waiting for Scheduled Task"
exit 1
}
# Verify Result
$St = Get-ScheduledTask -TaskName $TaskName
$Result = (Get-ScheduledTaskInfo -InputObject $St).LastTaskResult
if ($Result -eq 0) {
Write-Output "Completed Succesfully"
}
else {
Write-Output "Error running Schedule task, error code = $('0x{0:x}' -f $Result)"
}
# Cleaning up
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
Remove-Item -Path "$env:Windir\RunUserGPO.vbs" -Force
We simply add the content to a Run Script in Configuration Manager which we then can trigger for one or multiple clients.
The result will look like this in the console as an example:
And on the client we can see that the User Group Polices where processed.
I hope you will find it useful!
Good one. If, I remember correctly same can be achieved through GPO as well. Correct me, If, I am wrong.
Thanks for sharing the script.
Would love to see more post like this with different scripts. One of the biggest features for us with 1902 was “Scripts” We are constantly adding new ones as their use cases come up. It is always interesting to see what other admins are doing as well
Hi Jörgen,
This is a life saver. We need to trigger a silent GPUPDATE in user context on users’ machines via Scheduled task and the current Powershell solution is generating unwanted powershell pop-up windows.
Calling the vbscript that you wrote is working like a charm, no more unwanted “blue screens” on users’ machines.
Thank you!
Hi Jorgen,
This looks great, the only thing I would update it the username check code. I found the Win32_ComputerSystem doesn’t always identify the logged in user correctly, I think when user RDP to the machine or something similar. I would add the check for the explorer.exe process check:
# Check for logged in user
$ExplorerProcess = Get-Process explorer -ErrorAction SilentlyContinue
$UserName = (Get-WmiObject Win32_ComputerSystem).UserName
If (($UserName -ne $null) -or ($ExplorerProcess -ne $null)) {
fnLogWrite ” $UserName – user was detected as logged in… “
Do you have something similar for updating the Computer GPO’s instead of the User GPO’s?