转载:https://www.coder.work/article/2967857
原文:https://stackoverflow.com/questions/30533924/c-sharp-file-not-found-in-system32-when-running-in-32-bit
‘quser’ is not recognized as an internal or external command, operable program or batch file.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c quser /server:SomeServer";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
所以运行的完整命令是
cmd.exe /c quser /ser:SomeServer
当我直接执行它时运行良好,但在 C# 中失败。
我在这里发现了一个没有答案的类似问题: Executing Quser windows command in C#; Returning result to String 。不过,这个问题没有 quser not recognized 消息。
为什么从代码运行时无法识别命令?
我尝试像这样直接运行 quser 命令,但是我找不到文件…奇怪
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = @"c:\Windows\System32\quser.exe";
p.StartInfo.Arguments = @"/server:SomeServer";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
我们发现在 64 位运行它,它找到了。当作为 AnyCPU 或 32 位运行时,它似乎在 SysWOW64 中查找,即使我直接告诉它在 System32 中查找
自己做了个测试这个方法是好使的,可以解决问题!
所以解决方案是上述中讨论的一样,System32文件夹在某些构建中重定向到SysWOW64,导致quser显示调用结果为 “”。要解决这个办法:如下
1、using System.Runtime.InteropServices;
2、在类文件的顶部添加如下内容
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int Wow64EnableWow64FsRedirection(ref IntPtr ptr);
3、在进行quser调用之前,进行以下调用
IntPtr val = IntPtr.Zero;
Wow64DisableWow64FsRedirection(ref val);
4、调用quser后,恢复更改
Wow64EnableWow64FsRedirection(ref val);
完整样本:
using System.Runtime.InteropServices;
...
namespace CSharpTests
{
public class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int Wow64EnableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int Wow64RevertWow64FsRedirection(ref IntPtr ptr);
static void Main(string[] args)
{
IntPtr val = IntPtr.Zero;
Wow64DisableWow64FsRedirection(ref val);
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c quser";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Wow64RevertWow64FsRedirection(ref val);
p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c quser";
p.Start();
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
}
}
}
结果:
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
ebrown console 1 Active none 05/18/2015 09:2
1
‘quser’ is not recognized as an internal or external command,
operable program or batch file.
上面的图片也是我做的测试,和这个结果一样的
如您所见,第一次 quser 调用成功了,因为我们告诉操作系统停止重定向到 SysWOW64 ,一旦我们重新启用它,调用就会失败。
我确信这种保护是有原因的,但有时您 并不需要它。
其他注意事项:
谨慎的做法是让实现此模式的人首先检测是否需要应用变通方法。这种检测可以通过使用以下 bool 值来完成:
Environment.GetFolderPath(Environment.SpecialFolder.SystemX86).Contains("System32")
如果是 false bool 值,则您需要检查:
File.Exists(@"c:\windows\System32\FILENAMEHERE")
在这种情况下:
File.Exists(@"c:\windows\System32\qdisk.exe")
改编自:
http://blog.airesoft.co.uk/2010/09/wow-disabling-wow64-fs-redirection-can-cause-problems-who-knew/
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx
https://docs.microsoft.com/zh-cn/windows/win32/winprog64/file-system-redirector?redirectedfrom=MSDN