You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过msg命令向服务器所有用户发送交互弹窗并捕获响应?

实现方案

msg.exe从设计上就是单向通知工具,没有提供返回用户交互结果的接口,无法直接捕获用户选择。要实现给所有在线用户推送可捕获返回值的确认弹窗,核心思路是把你已经写好的带交互逻辑的PowerShell脚本,直接投递到每个活跃用户会话内执行,不需要依赖msg做交互。

方案1:基于psexec投递(运维场景最常用,稳定性高)

这个方案无复杂配置,弹窗效果和你本地测试的Wscript.Shell弹窗完全一致,支持30秒超时、置顶模态、返回值捕获。

  • 第一步:枚举服务器上所有处于活跃状态的用户会话ID,用系统自带的query session命令即可解析:
    # 提取所有状态为Active的用户会话ID
    $activeSessions = query session | Where-Object { $_ -match '^(\s+)?[^\s]+\s+\d+\s+Active' } | ForEach-Object {
        $_.Split(' ', [StringSplitOptions]::RemoveEmptyEntries)[2]
    }
    
  • 第二步:把弹窗交互逻辑封装成独立脚本,存到所有用户可读的公共路径比如C:\ProgramData\shutdown_confirm.ps1,加锁避免多用户重复调用取消API:
    # shutdown_confirm.ps1 内容
    $lockFile = "C:\ProgramData\shutdown_cancel.lock"
    # 已有其他用户触发过取消则直接退出
    if (Test-Path $lockFile) { exit }
    
    $wshell = New-Object -ComObject Wscript.Shell
    # 参数说明:30=超时秒数,0x4=显示是/否按钮,0x20=问号图标,0x1000=系统置顶模态窗
    $result = $wshell.Popup(
        "服务器已触发关机流程,您是否仍在工作?`n本提示30秒后将自动判定您正在工作,取消本次关机",
        30,
        "关机操作确认",
        0x4 + 0x20 + 0x1000
    )
    
    # 返回值6=点击「是(我在工作)」,-1=超时无操作,两种情况均触发取消
    if ($result -eq 6 -or $result -eq -1) {
        New-Item -Path $lockFile -ItemType File -Force | Out-Null
        $postParams = @{ trigger = "user_confirm_or_timeout" }
        Invoke-WebRequest -Uri '替换为你的取消关机API地址' -Method POST -Body $postParams -UseBasicParsing
    }
    
  • 第三步:遍历所有活跃会话,用psexec把脚本投递到对应会话的用户桌面运行:
    # 提前清理历史锁文件
    Remove-Item "C:\ProgramData\shutdown_cancel.lock" -Force -ErrorAction SilentlyContinue
    foreach ($sessionId in $activeSessions) {
        # -i 指定运行的会话ID,-d 不等待进程返回,避免阻塞其他会话的脚本投递
        psexec -i $sessionId -d powershell.exe -ExecutionPolicy Bypass -File "C:\ProgramData\shutdown_confirm.ps1"
    }
    

方案2:无第三方工具依赖(原生计划任务投递)

如果不想使用psexec,可以用系统自带的计划任务功能完成脚本投递,核心交互逻辑和方案1完全一致,只需要把投递步骤替换为遍历会话创建临时计划任务即可:

foreach ($sessionId in $activeSessions) {
    $taskName = "TempShutdownConfirm_$sessionId"
    # 创建绑定指定会话、仅用户交互时运行的临时任务
    schtasks /create /tn $taskName /sc once /st 00:00 /ru "Users" /it /tr "powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\shutdown_confirm.ps1" /f | Out-Null
    # 立即执行任务
    schtasks /run /tn $taskName | Out-Null
    # 执行完成后自动删除临时任务
    Start-Sleep -Seconds 1
    schtasks /delete /tn $taskName /f | Out-Null
}

注意事项

  • 不要尝试hack msg命令获取返回值,该工具内部没有实现选择结果的输出接口,所有相关尝试都无法稳定生效。
  • 弹窗务必加0x1000系统模态参数,避免被用户打开的其他窗口遮挡导致看不到提示。
  • 注意核对Popup返回值和按钮的对应关系:返回6为点击「是」,返回7为点击「否」,返回-1为超时,可根据自己的文案调整判断逻辑,不要搞反触发条件。
  • 锁文件机制必须保留,避免多用户同时触发时重复调用取消API。

内容的提问来源于stack exchange,提问作者Mochael_DLite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:54:17