【问题标题】:.NET File.Exists doesn't work in Windows\System32\Drivers folder?.NET File.Exists 在 Windows\System32\Drivers 文件夹中不起作用?
【发布时间】:2009-05-26 20:57:18
【问题描述】:

进程已提升,我确保 VS 调试器中的路径正确(我使用的是 Environment.GetFolderPath(Environment.SpecialFolder.System) 而不是硬编码),但 File.Exists 仍然返回 false。

我需要这个的原因是为了确保安装一些第 3 方驱动程序,因为它们的注册表设置在卸载时不会被删除。

我知道写入是通过虚拟化重定向的,但对于检查文件的存在也是如此吗?

【问题讨论】:

  • 对我来说很好。你的环境是什么?

标签: .net windows-vista 64-bit drivers


【解决方案1】:

是的,虚拟化发生在非常低​​的级别。 File.Exists 方法基本上调用 Win32 CreateFile 方法并检查错误。 CreateFile 被 WOW 子系统重定向。

您可以在调用之前暂时禁用虚拟化。

[DllImport( "kernel32", CharSet=CharSet.Unicode, SetLastError=true )]
public static extern bool Wow64DisableWow64FsRedirection( ref IntPtr oldValue );

[DllImport( "kernel32", CharSet=CharSet.Unicode, SetLastError=true )]
public static extern bool Wow64RevertWow64FsRedirection( IntPtr oldValue );

当然,要完整,您必须在虚拟化打开和关闭的情况下检查文件是否存在。这同样适用于检查注册表项。

public static bool FileExists( string path )
{
    if( File.Exists( path ) ) return true;
    IntPtr oldValue = IntPtr.Zero;
    try
    {
        if( Environment.GetEnvironmentVariable( "PROCESSOR_ARCHITEW6432" ) == null )
            return false;

        Wow64DisableWow64FsRedirection( ref oldValue );
        if( File.Exists( path ) ) return true;

        return false;
    }
    finally
    {
        if( oldValue != IntPtr.Zero )
            Wow64RevertWow64FsRedirection( ref oldValue );            
    }   
}

更新:您可能还需要在禁用 WOW 重定向之前检查操作系统版本,因为早期版本的 XP(我相信是 Pre SP2)不公开这些方法。

更新 2: 添加了 64 位操作系统检查。所有 64 位版本的操作系统都实现了这些方法,如果在 64 位操作系统上运行,您只需禁用状态即可。

【讨论】:

  • 那么通过 try/finally 我还需要检查操作系统版本吗?我想如果不支持 finally 块也会抛出。
  • 是的 - finally 块仍然调用 Wow64XXX 方法。
【解决方案2】:

您的进程是 32 位还是 64 位?驱动程序是 64 还是 32?我的意思是,您的主机操作系统可能会将您重定向到 Wow64 文件夹。

【讨论】:

    【解决方案3】:

    您是否为您的应用尝试过disabling folder virtualization?您需要添加一个清单文件,其中包含:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
            <security>
                <requestedPrivileges>
                    <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
                </requestedPrivileges>
            </security>
        </trustInfo>
    </assembly>
    

    但是,如果您需要写入这些文件夹,则必须发送至request admin ability。为此,请将 xml 中的 level="asInvoker" 更改为 level="requireAdministrator"

    【讨论】:

      【解决方案4】:

      这是一个虚拟化问题 - 文件不存在。您必须在包含虚拟化文件的文件夹中查找它。

      【讨论】:

        【解决方案5】:

        如果您有权限,为什么不尝试在代码中的相同位置创建一个文件,然后看看它在哪里结束?正如另一个人所建议的那样,Windows 可能会根据一些设置重定向您的呼叫。

        另外,您可以尝试做一个 DirectoryInfo 并枚举其中包含的文件,看看是否有任何熟悉的内容。

        【讨论】:

          猜你喜欢
          • 2013-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多