C# 程序以 32 位运行时在 System32 中找不到文件的解决方案

C# 程序以 32 位运行时在 System32 中找不到文件的解决方案

问题描述

最近使用C#开发windows应急响应信息收集的工具,发现获取不到系统中的事件日志的文件。

在ide中下断点调试。

报错提示:ERROR 3 (0x00000003) Accessing Source Directory C:\Windows\System32\WINEVT\LOGS\
The system cannot find the path specified.

而在本地的cmd中执行确定没有任何问题,一开始以为是C#程序的执行权限不够,后来给了管理员权限执行也无法解决。

解决方案

参考 https://stackoverflow.com/questions/30533924/c-sharp-file-not-found-in-system32-when-running-in-32-bit

以 64 位运行程序没有问题,当以 AnyCPU 或 32 位运行时,程序只在 SysWOW64 中查找,即使要求在 System32 中查找。

使用以下命名空间:

using System.Runtime.InteropServices;

在类文件的顶部添加以下内容。

[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);

在执行cmd之前,使用如下:

 IntPtr val = IntPtr.Zero;
 Wow64DisableWow64FsRedirection(ref val);

cmd执行完成后,还原更改:

Wow64EnableWow64FsRedirection(ref val);

重新下断点调试后正常执行。

代码实现

修改后的完整代码如下:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace GetInfo
{
  public class Cmd
  {
    [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);

    private Process proc = (Process) null;

    public Cmd() => this.proc = new Process();

    public string RunCmd(string cmd)
    {
      IntPtr val = IntPtr.Zero;

      Wow64DisableWow64FsRedirection(ref val);    //禁用重定向
      
      this.proc.StartInfo.CreateNoWindow = true;
      this.proc.StartInfo.FileName = "cmd.exe";
      this.proc.StartInfo.UseShellExecute = false;
      this.proc.StartInfo.RedirectStandardError = true;
      this.proc.StartInfo.RedirectStandardInput = true;
      this.proc.StartInfo.RedirectStandardOutput = true;
      this.proc.Start();
      this.proc.StandardInput.WriteLine(cmd);
      this.proc.StandardInput.WriteLine("exit");
      string end = this.proc.StandardOutput.ReadToEnd();
      this.proc.Close();
      
      Wow64RevertWow64FsRedirection(ref val);    //开启重定向

      return end;
    }

原因分析

32位程序存在文件系统重定向的问题,64位程序则不会。在代码中禁用重定向即可。

因为%windir%\System32专为 64 位应用程序保留,所以在 64 位版本的 Windows 上,尝试访问该%windir%\System32目录的 32 位应用程序会自动且透明地重定向到 32 位%windir%\SysWOW64目录。

首先,确保程序确实属于 64 位系统文件夹。Windows 执行此自动重定向是有原因的。32 位的东西不在%windir%\System3264 位版本的 Windows 上的文件夹中

赞赏

微信赞赏支付宝赞赏

Zgao

愿有一日,安全圈的师傅们都能用上Zgao写的工具。

发表评论