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

使用PsExec和C#远程运行程序:已连接但无法正常执行

解决C#调用PsExec远程执行.exe安装程序的阻塞问题

哥们,你现在的代码逻辑有几个致命问题,导致远程程序没启动,还卡在WaitForExit()上。我帮你拆解问题并给出修正方案:

核心问题分析

  • 输入流混淆:你先启动本地cmd,然后输入PsExec命令打开远程cmd,接着又输入commandToRunRemote——但这个命令其实是发给本地cmd的,根本没传到远程控制台里,所以远程机器上完全没启动目标程序,本地cmd还在等着输入,自然会无限阻塞。
  • 多此一举的中间步骤:PsExec本身可以直接指定要远程运行的程序和参数,不需要先启动远程cmd再输入命令,这步完全是画蛇添足。
  • 标准流死锁风险:你在WaitForExit()之后才去读StandardError和StandardOutput,如果输出缓冲区满了,远程进程会卡住,导致本地进程永远等不到退出信号。

修正后的代码

直接用PsExec远程调用目标安装程序,去掉多余的cmd步骤,同时处理好标准流的读取:

using System;
using System.Text;
using System.Diagnostics;

class RemoteInstaller
{
    static string hostname = @"111.111.1.11";
    static string username = "myusername";
    static string password = "mypassword";

    public string RunRemoteInstaller()
    {
        try
        {
            // 注意:如果PsExec不在系统PATH里,要写完整路径,比如@"C:\Tools\PsExec.exe"
            string psexecPath = @"psexec.exe";
            // 远程机器上的目标程序路径
            string remoteExePath = @"C:\Users\MyUser\Desktop\MyInstaller\DLLConfiguration.exe";
            // 目标程序的参数
            string exeArguments = @"""C:\Users\MyUser\Desktop\MyInstaller\Installers"" -s -update";

            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = psexecPath,
                // 拼接PsExec的完整参数:远程主机、会话、工作目录、凭据、目标程序、程序参数
                Arguments = $@"\\{hostname} -i 1 -w ""C:\Users\MyUser\Desktop\Updater"" -u {username} -p {password} ""{remoteExePath}"" {exeArguments}",
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true, // 不需要显示窗口就设为true,需要交互就设为false
                WindowStyle = ProcessWindowStyle.Hidden
            };

            // 使用using确保进程资源被正确释放
            using (Process process = new Process { StartInfo = startInfo })
            {
                StringBuilder outputBuilder = new StringBuilder();
                StringBuilder errorBuilder = new StringBuilder();

                // 异步读取输出和错误,避免缓冲区满导致进程挂起
                process.OutputDataReceived += (sender, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                        outputBuilder.AppendLine(e.Data);
                };
                process.ErrorDataReceived += (sender, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                        errorBuilder.AppendLine(e.Data);
                };

                process.Start();
                // 开始异步读取
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                // 设置超时时间(比如30秒),避免无限等待
                bool didExit = process.WaitForExit(30000);
                if (!didExit)
                {
                    process.Kill();
                    return $"ERROR: 进程超时未退出。错误信息:{errorBuilder.ToString()}";
                }

                string output = outputBuilder.ToString();
                string error = errorBuilder.ToString();

                if (process.ExitCode == 0)
                {
                    return $"执行成功!输出信息:{output}";
                }
                else
                {
                    return $"执行失败。退出码:{process.ExitCode}。错误信息:{error}。输出信息:{output}";
                }
            }
        }
        catch (Exception ex)
        {
            return $"发生异常:{ex.Message}";
        }
    }
}

关键改进说明

  • 直接调用PsExec执行目标程序:跳过中间的远程cmd,让PsExec直接在远程机器上启动你的安装程序,参数直接传递,彻底解决输入流混淆的问题。
  • 异步读取标准流:用BeginOutputReadLine和BeginErrorReadLine异步读取输出,防止缓冲区满导致进程卡死,这也是之前WaitForExit无限等待的重要原因。
  • 超时处理:设置30秒超时,超时后主动终止进程,避免程序无限挂起。
  • 资源管理:用using块管理Process对象,确保进程资源被正确释放。

额外注意事项

  • 确保本地机器能访问远程机器的ADMIN$共享(PsExec依赖这个),远程防火墙允许445端口通信。
  • 确认你的用户名和密码拥有远程机器的管理员权限,PsExec需要管理员权限才能远程执行程序。
  • 检查-i 1指定的会话ID是否正确:可以在远程机器上运行query session命令查看当前交互会话的ID,确保和你指定的一致(如果安装程序是GUI程序,这个参数很重要)。
  • 确认远程机器上的所有路径都存在(包括目标程序路径和参数里的Installers路径),路径写错会导致程序无法启动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:37:12