求助:无法通过psexec.exe远程启动进程的技术问题
搞定PsExec远程启动vstest测试的那些坑
看你的描述,你是通过PsExec远程触发服务器上的cmd脚本,再让控制台应用调用vstest.console.exe跑测试,但肯定是卡壳了对吧?结合我处理过的类似场景,给你梳理几个最容易踩的坑和解决办法:
1. PsExec的权限和会话是重灾区
PsExec默认是在**服务会话(0号)**运行的,而vstest有时候依赖桌面会话的组件,或者需要交互式权限,这时候就会莫名其妙失败。
- 解决办法:
- 执行PsExec的时候加
-i参数指定交互式会话,比如psexec \\你的服务器名 -i 2 -u 域账号 -p 密码 cmd /c "你的脚本路径"。这里的2是会话ID,你可以在服务器上用quser命令查当前登录用户的会话ID,替换成对应的数字就行 - 一定要用有服务器本地管理员权限的账号,而且这个账号得有测试文件所在目录的读写权限,不然连结果文件都生成不了
- 执行PsExec的时候加
2. VSTest的路径和结果文件路径别瞎写
你的控制台代码里生成了带时间戳的.trx文件名,但如果没指定完整路径,默认会生成在PsExec的工作目录(一般是C:\Windows\System32),这里权限很严,根本写不进去。
- 解决办法:
- 调用
vstest.console.exe时用完整路径,别依赖环境变量,比如C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\TestPlatform\vstest.console.exe,不同VS版本路径可能不一样,自己对应着改 - 在代码里给结果文件指定完整的输出目录,比如:
var resultFilePath = Path.Combine(@"D:\TestResults", resultFileName); // 调用vstest的时候加上参数 /logger:trx;LogFileName=" + resultFilePath
- 调用
3. Cmd脚本得先把工作目录弄对
服务器上的cmd脚本如果没切换到控制台应用的目录,运行的时候可能找不到依赖文件,直接报错。
- 解决办法:
在脚本开头加一句cd /d "你的控制台应用所在目录",比如cd /d "D:\MyConsoleApp",确保工作目录正确。另外脚本里调用完控制台应用后,可以加echo %errorlevel%看看退出码,判断是不是控制台应用本身跑失败了
4. 加日志!加日志!加日志!
遇到这种远程执行的问题,光靠猜没用,得靠日志定位。
- 给cmd脚本加日志:
@echo off echo 脚本启动时间:%date% %time% >> D:\ScriptLogs\run_test.log cd /d "D:\MyConsoleApp" echo 当前工作目录:%cd% >> D:\ScriptLogs\run_test.log MyConsoleApp.exe >> D:\ScriptLogs\run_test.log 2>&1 echo 控制台应用退出码:%errorlevel% >> D:\ScriptLogs\run_test.log - 给控制台应用里的vstest调用加日志,把命令行参数、输出、错误都记录下来:
var vstestPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\TestPlatform\vstest.console.exe"; var testAssembly = @"D:\Tests\MyTest.dll"; var resultFileName = $"testresults{DateTime.Now:yyyyMMddHHmmss}.trx"; var resultFilePath = Path.Combine(@"D:\TestResults", resultFileName); var startInfo = new ProcessStartInfo { FileName = vstestPath, Arguments = $"\"{testAssembly}\" /logger:trx;LogFileName=\"{resultFilePath}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (var process = Process.Start(startInfo)) { string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); // 把日志写到指定目录 File.WriteAllText(@"D:\TestLogs\vstest_out.log", output); File.WriteAllText(@"D:\TestLogs\vstest_err.log", error); if (process.ExitCode != 0) { // 这里可以加失败后的处理逻辑 } }
5. 别忘了检查防火墙和组策略
如果服务器防火墙开着,得确保允许SMB(445端口)和RPC(135端口)的通信,不然PsExec连不上服务器。要是在域环境,还要确认组策略没禁用PsExec的使用。
内容的提问来源于stack exchange,提问作者Roman Suska
相关产品推荐
相关产品推荐

