我需要检查文件(通过UNC path在远程服务器上)是否存在(这里的权限不是问题;我需要进行模拟等)。

我使用CreateFileW函数创建file handle
我也尝试过GetFileAttributesEx,但是行为是相同的。

HANDLE CreateFileW(
  LPCWSTR               lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);

如果我处理UNC paths,由于UNC cache(不同的进程会复制或删除我需要检查的文件),可能会导致错误的结果。
它取决于FileNotFoundCacheLifetime注册表项的值(默认情况下,该值为10秒)。
// lets say I would like to check a file
// in the beginning the file exists
// than another process delete this file
// (e.g. executing drop database command by sql server)
// than another process copies this file back
// and all steps above takes less then FileNotFoundCacheLifetime value

// path = @"\\server\C$\Tmp\Folder\database\myDb.mdf"
private static void Test(string path)
{
    File.Exists(path);                              //exists
    Directory.Exists(Path.GetDirectoryName(path));  //exists

    using (var handle = CreateFile(path, EFileAccess.GenericRead, EFileShare.Read, IntPtr.Zero,
        ECreationDisposition.OpenExisting, EFileAttributes.Normal, IntPtr.Zero))
    {
        if (handle == null || handle.IsInvalid)
        {
            //FileNotFoundCacheLifetime = 0  => exists
            //FileNotFoundCacheLifetime = 10 => Win32Exception - The system cannot find the file specified
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
    }
}

[DllImport("kernel32.dll", EntryPoint = "CreateFileW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeFileHandle CreateFile(
    string lpFileName,
    EFileAccess dwDesiredAccess,
    EFileShare dwShareMode,
    IntPtr lpSecurityAttributes,
    ECreationDisposition dwCreationDisposition,
    EFileAttributes dwFlagsAndAttributes,
    IntPtr hTemplateFile);

#region CreateFile
[Flags]
public enum EFileAccess : uint
{
    GenericRead = 0x80000000,
    GenericWrite = 0x40000000,
    GenericExecute = 0x20000000,
    GenericAll = 0x10000000,
}

[Flags]
public enum EFileShare : uint
{
    None = 0x00000000,
    Read = 0x00000001,
    Write = 0x00000002,
    Delete = 0x00000004,
}

public enum ECreationDisposition : uint
{
    New = 1,
    CreateAlways = 2,
    OpenExisting = 3,
    OpenAlways = 4,
    TruncateExisting = 5,
}

[Flags]
public enum EFileAttributes : uint
{
    Readonly = 0x00000001,
    Hidden = 0x00000002,
    System = 0x00000004,
    Directory = 0x00000010,
    Archive = 0x00000020,
    Device = 0x00000040,
    Normal = 0x00000080,
    Temporary = 0x00000100,
    SparseFile = 0x00000200,
    ReparsePoint = 0x00000400,
    Compressed = 0x00000800,
    Offline = 0x00001000,
    NotContentIndexed = 0x00002000,
    Encrypted = 0x00004000,
    Write_Through = 0x80000000,
    Overlapped = 0x40000000,
    NoBuffering = 0x20000000,
    RandomAccess = 0x10000000,
    SequentialScan = 0x08000000,
    DeleteOnClose = 0x04000000,
    BackupSemantics = 0x02000000,
    PosixSemantics = 0x01000000,
    OpenReparsePoint = 0x00200000,
    OpenNoRecall = 0x00100000,
    FirstPipeInstance = 0x00080000
}
#endregion CreateFile

您知道如何获得未缓存的结果吗?
基本上,我可以禁用我知道的UNC cache
在这里,我需要一种不同的方法-如何针对特定的方法调用准确地获取未缓存的结果。

我知道以下方法-$NOCSC$(@"\\server$NOCSC$\C$\folder\file")修饰符,但不幸的是,它不适用于所有操作系统。
File.Exists()Folder.Exists()可以工作,但是我需要fileapi,因为它支持长路径(基本上,这只是一个可行的解决方案)。

对我来说,另一个好的解决方案是以编程方式清理UNC文件系统缓存(再次精确地在特定方法调用之前)。

最佳答案

blogs mdsn上有一条针对长路径的修复程序(根据您对这篇文章的评论),它是.net 4.6.2及更高版本的申请人。

您将必须将应用程序 list 文件项添加到您的项目中,博客中提供了有关该过程的详细指南,但对于所有人而言,这似乎是一个很好的解决方案,而没有任何必要的麻烦。

在示例中,他们确实在控制台应用程序上对其进行了测试,因此您将必须确定如何对解决方案进行适当的调整。

关于c# - 如何指定createfilew函数获取未缓存的结果?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57020034/

10-13 00:08