c# - 如何指定 createfilew 函数获取未缓存的结果?
问题描述
我需要检查一个文件(在远程服务器上通过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 缓存而得到错误的结果(不同的进程复制或删除我需要检查的文件)。它取决于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 文件系统缓存(同样在特定方法调用之前)。
解决方案
在博客 mdsn上有一个针对长路径的修复(根据您对这篇文章的评论),它是 .net 4.6.2 及更高版本的申请人。
您必须将应用程序清单文件项添加到您的项目中,博客中有详细的流程指南,但总而言之,这似乎是解决您的问题的好方法,没有任何不必要的麻烦。
在示例中,他们确实在控制台应用程序上对其进行了测试,因此您必须弄清楚如何对您的解决方案进行适当的调整。
推荐阅读
- python - 将字符串列表转换为数字但保留空格 - Python
- c# - C#条件调整
- python - 笔记本验证失败 | 木星
- c# - 如何将 Serilog 依赖注入到 .NET 控制台应用程序中的其余类中
- c# - Selenium SendKeys() 和 Click() 在链接导航后静默失败
- javascript - 将数组中的迭代元素推入空数组不起作用
- php - 特定页面的不同 Woocommerce 产品缩略图大小
- flutter - Flutter 中 Hive 框中的记录过滤和排序
- android - 通知管理器不显示通知
- android - 没有 UI 的 Android 应用程序:如何在每次运行应用程序时停止瞬时闪烁