使用Invoke-CIMMethod批量安装SCCM应用的脚本跨机运行异常求助
问题排查与修正方案
根因定位
- 循环变量名不匹配:脚本第一行将读取的计算机列表存入单数变量
$computer,但foreach循环遍历的是从未定义的复数变量$computers。PowerShell对未定义变量默认按$null处理,遍历空值的foreach循环一次都不会执行内部逻辑,因此批量运行时既无输出、也不触发安装、也无报错。单台测试能正常运行,是因为测试时移除了循环、手动指定了单台计算机名,没有触发这段错误逻辑。 - 无空值校验:远程计算机离线、应用名称匹配失败、WMI权限不足时,查询到的
$Application为空,脚本直接将空值传入Invoke-CimMethod,方法会静默失败无任何反馈。 - 冗余无效代码:脚本中定义的
$Instance变量执行了和$Application完全重复的查询,后续从未使用。 - 覆盖内置自动变量:使用
$Args作为自定义参数哈希表的变量名,会覆盖PowerShell内置的$Args自动变量,存在潜在运行风险。
修正后可直接批量运行的脚本
# 读取计算机列表时自动过滤空行 $computers = Get-Content -Path c:\temp\computers.txt | Where-Object { $_.Trim() -ne "" } foreach ($computer in $computers) { if ([string]::IsNullOrWhiteSpace($computer)) { continue } $appName = 'AppNameHere' # 远程查询目标应用,连接失败时输出提示并跳过 try { $Application = Get-CimInstance ` -ClassName CCM_Application ` -Namespace "root\ccm\clientSDK" ` -ComputerName $computer -ErrorAction Stop | Where-Object {$_.Name -like "*$appName*"} } catch { Write-Host "连接 $computer 失败:$($_.Exception.Message)" continue } # 无匹配应用时直接跳过 if (-not $Application) { Write-Host "$computer 上未找到匹配 [$appName] 的应用" continue } # 自定义参数变量,避免覆盖$Args内置变量 $installParams = @{ EnforcePreference = [UINT32] 0 Id = $Application.Id IsMachineTarget = $Application.IsMachineTarget IsRebootIfNeeded = $False Priority = 'High' Revision = $Application.Revision } Write-Host "正在向 $computer 发起 [$appName] 安装请求..." try { $installResult = Invoke-CimMethod -Namespace ROOT\ccm\ClientSDK ` -ClassName CCM_Application ` -ComputerName $computer ` -MethodName Install ` -Arguments $installParams -ErrorAction Stop Write-Host "$computer 安装请求返回码:$($installResult.ReturnValue)(0代表请求已成功触发)" } catch { Write-Host "$computer 安装请求发起失败:$($_.Exception.Message)" } }
运行注意事项
- 权限要求:执行脚本的账号必须对远程计算机有本地管理员权限,否则无法访问
root\ccm\clientSDK命名空间 - 网络要求:远程计算机需开启WinRM服务、允许WMI远程访问,无需额外通过Invoke-Command建立会话
- 匹配规则:建议在应用名称前后加通配符,避免因版本后缀、发布者信息导致名称匹配失败
- 状态校验:
Install方法仅负责向客户端发起安装触发请求,实际安装状态可在客户端Software Center或CcmExec.log日志中确认
内容的提问来源于stack exchange,提问作者ferosi44
相关产品推荐
相关产品推荐

