.NET应用执行%WINDIR%\System32下批处理文件失败排查
老兄,我完全懂你的处境——这个问题真不是那些热门重复问题的范畴,因为常规方案根本搞不定它。你说调用其他位置的批处理都正常,唯独碰%WINDIR%\System32相关的就出问题,结合你的代码和报错信息,我大概率能锁定原因,给你几个可行的解决办法。
先理清楚你的场景细节:
- 你的批处理内容:
telnet 10.147.36.20 11211 pause - 执行用的C#代码:
var psi = new ProcessStartInfo(entry.ExecutablePath); Process.Start(psi);
- 报错开头是
'te...——这基本就是命令找不到的典型表现,大概率是telnet.exe没被正确定位到。
核心原因:Windows文件系统重定向搞的鬼
如果你的程序是32位的,在64位Windows系统上运行时,系统会自动触发文件系统重定向:所有对C:\Windows\System32的访问,都会被偷偷转到C:\Windows\SysWOW64目录(这是32位程序的专属系统目录)。而64位系统里的telnet.exe默认只在System32里,SysWOW64根本没有这个文件,所以你的批处理执行时自然找不到telnet命令,就会抛出那种半截的错误。
三个可行的解决办法
1. 临时禁用文件系统重定向
在启动进程前,先禁用重定向,执行完再恢复,这样32位程序就能直接访问64位的System32目录。给你写个完整的代码示例:
using System; using System.Diagnostics; using System.Runtime.InteropServices; public static class ProcessHelper { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr); public static void StartSystem32Process(string executablePath) { IntPtr redirectPtr = IntPtr.Zero; try { // 仅在64位系统上的32位程序中禁用重定向 if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) { Wow64DisableWow64FsRedirection(ref redirectPtr); } var psi = new ProcessStartInfo(executablePath); Process.Start(psi); } finally { // 无论如何都要恢复重定向,避免影响后续操作 if (redirectPtr != IntPtr.Zero) { Wow64RevertWow64FsRedirection(redirectPtr); } } } }
之后调用ProcessHelper.StartSystem32Process(entry.ExecutablePath)就行。
2. 直接指定Sysnative目录的telnet
64位Windows有个隐藏的Sysnative目录,专门让32位程序绕过重定向访问64位的System32文件。你只需要修改批处理里的命令:
%WINDIR%\Sysnative\telnet.exe 10.147.36.20 11211 pause
这样不管是32位还是64位程序调用,都能精准找到正确的telnet.exe。
3. 把程序编译为64位
如果你的项目没有必须用32位的限制,直接在Visual Studio里把项目的平台目标改成x64(项目属性→生成→平台目标),编译成64位程序后,就不会触发文件系统重定向,直接就能访问System32目录下的文件,问题自然解决。
快速验证方法
你可以手动打开32位的命令提示符(路径是C:\Windows\SysWOW64\cmd.exe),然后执行你的原批处理,看看是不是会弹出'telnet' 不是内部或外部命令,也不是可运行的程序或批处理文件的错误。如果是的话,那百分百就是文件系统重定向的问题,用上面的办法就能搞定。
内容的提问来源于stack exchange,提问作者AngryHacker

