我在通过 ConfigMgr(SCCM) 客户端通过脚本运行 PowerShell 时遇到了一个有趣的问题。SCCM Current Branch 的一个相对较新的功能是能够通过 SCCM 代理实时在目标节点上运行 PowerShell 脚本。此代理在SYSTEM
上下文中运行,我编写了许多实用程序脚本,这些脚本可以同时从多台计算机上的 SCCM 管理控制台运行。
我目前正在开发的 PS 脚本应该可以对计算机和登录用户的 GPO 进行 GPUpdate。策略的计算机部分通过上下文可以正常工作SYSTEM
;但是,要对 GPO 的用户部分进行 GPUpdate,我使用任务调度程序代码以登录用户身份运行它。
它按预期工作,但是用户 GPUpdate 进程继续停留在内存中,我一直不明白为什么。
然后我突然想到,这可能是因为用户在尝试手动运行 GPUpdate 时,会在 cmd 控制台上看到注销提示(以完成客户端 GPO 扩展处理)。至少这是我现阶段的假设,但我不知道如何深入挖掘。
由于我的脚本在这个 SCCM 代理“沙箱”内运行,而该代理“沙箱”又启动另一个运行用户上下文 GPupdate 的 Powershell,我不知道是否有办法将“否”答案提供给 gpupdate 的注销提示?
有任何想法吗?
以下是在系统环境中在目标机器上运行的完整 PowerShell 脚本。
#
cmd /c gpupdate /target:computer /force | Out-Null
$ExplorerProcess = Get-WmiObject win32_process | Where-Object { $_.name -Match 'explorer'}
$LoggedOnUser = if($ExplorerProcess.getowner().user.count -gt 1){ $ExplorerProcess.getowner().user[0] }else{ $ExplorerProcess.getowner().user }
If($LoggedOnUser.trim() -eq "") { "Computer GPUpdate Successful. No active user session" Return }
$TaskName = "Run User GPUpdate - $((Get-Date).ToString('dd-MM-yyyy-HH-mm-ss'))" $ShedService = New-Object -comobject 'Schedule.Service' $ShedService.Connect()
$Task = $ShedService.NewTask(0) $Task.RegistrationInfo.Description = 'Upser GPUpdate Description' $Task.Settings.Enabled = $true $Task.Settings.AllowDemandStart = $true $Task.Settings.DeleteExpiredTaskAfter = 'PT0S' $Task.Settings.StartWhenAvailable = $True
$trigger = $task.triggers.Create(1) $trigger.StartBoundary = [DateTime]::Now.AddSeconds(5).ToString("yyyy-MM-dd'T'HH:mm:ss") $trigger.EndBoundary = [DateTime]::Now.AddSeconds(30).ToString("yyyy-MM-dd'T'HH:mm:ss") $trigger.Enabled = $true
$ScriptCode = """ cmd /c gpupdate.exe /target:user /force """ $PwshArgument = "-ExecutionPolicy ByPass -NoProfile -WindowStyle Hidden -command $ScriptCode"
$action = $Task.Actions.Create(0) $action.Path = 'Powershell.exe' $action.Arguments = $PwshArgument $taskFolder = $ShedService.GetFolder("\")
try{ $taskFolder.RegisterTaskDefinition($TaskName, $Task , 6, 'Users' , $null, 4) | Out-Null "Computer GPO and User $LoggedOnUser GPO update Successful" } Catch { "GPUpdate Failed - $($_.Exception.Message)" }
#
答案1
禁止 gpupdate 提示
考虑将/wait:0
参数和值与gpupdate
命令合并。这应该会抑制确认提示,从而允许 GP 继续处理,同时允许进一步的脚本逻辑继续执行,而无需先“等待”它完成。
gpupdate /force /wait:0
我过去曾经使用过类似的东西,并取得了良好的效果,但运行gpupdate /target:computer /force /wait:0
或gpupdate /target:user /force /wait:0
指定将哪个策略部分推送到机器和/或用户应该没有问题。
/等待:
设置在返回命令提示符之前等待策略处理完成的秒数。超过时间限制时,命令提示符会出现,但策略处理会继续。默认值为 600 秒。值
0
表示不等待。值-1
意味着无限期地等待。在脚本中,通过使用指定时间限制的该命令,您可以运行更新并继续执行不依赖于完成的命令更新。或者,您可以使用此命令而不指定时间限制,以让更新在其他依赖于它的命令运行之前完成运行。
/等待:
等待策略处理的秒数。
default
=600(10分钟)0
=不要等-1
=无限期等待
如果超出时间限制,命令提示符将返回,但策略处理将继续。