.NET File.Exists doesn't work in Windows\\Syst

2019-06-17 11:14发布

问题:

The process is elevated and I ensured that the path was correct in VS debugger (I'm using Environment.GetFolderPath(Environment.SpecialFolder.System) not hard coding it in) but File.Exists still returns false.

The reason I need this is a workaround for ensuring some 3rd party drivers are installed because their registry settings aren't removed on uninstall.

I know writes are redirected via virtualization but is this also true for checking a file's existence?

回答1:

Yes, virtualization happens at a very low level. The File.Exists method basically calls the Win32 CreateFile method and checks for errors. CreateFile is redirected by the WOW subsystem.

You can disable virtualization temporarily before calling.

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

Of course to be complete you'll have to check for file existence with virtualization on as well as off. The same applies for checking registry entries as well.

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

Update: You may also need to check the OS version before disabling the WOW redirection because earlier versions of XP (Pre SP2 I believe) do not expose those methods.

Update 2: Added OS check for 64-bit. All 64-bit versions of the OS implement these methods and you only need to disable the sate if running on a 64-bit OS.



回答2:

Is your process 32 bit or 64 bit? and are the drivers 64 or 32? What I'm getting at is that maybe your host OS redirects you to the Wow64 folder instead.



回答3:

Have you tried disabling folder virtualization for your app? You'll need add a manifest file containing:

<?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>

However, if you need to write to those folders you'll have to request admin ability. To do that, change level="asInvoker" to level="requireAdministrator" in the xml.



回答4:

This is an virtualization issue - the file just isn't there. You will have to look for it in the folder the contains the virtualized files.



回答5:

If you have the rights, why don't you attempt to create a file in the same location in your code, and see where it ends up? As suggested by another, Windows might be redirecting your call based on a few settings.

Also, you could try doing a DirectoryInfo and enumerating Files it contains to see if anything looks familiar.