由于这显然是一个不受支持的场景,我怀疑它是否可以在不使用一些低级文件访问的情况下完成。
您可以尝试做的是放弃FileInfo
并使用
File.Exists(path)
and File.ReadAllBytes(path)
。这些也许能够规避这个问题。
使用 SafeFileHandle 访问文件
以下内容未经测试
创建UnmanagedFileLoader
(下面的代码,取自MSDN)的实例,允许您创建一个SafeFileHandle
对象,该对象可以通过FileStream
以下方式传递给构造函数:
UnmanagedFileLoader ufl = new UnmanagedFileLoader(path);
FileStream fs = new FileStream(ufl.Handle, FileMode.Open);
注意:记得打电话 ufl.Handle.Dispose()
。
容我们说,这应该为您提供更多直接访问文件的权限,因此可以绕过强制执行 Windows 已有的有效文件名。
UnmanagedFileLoader 代码
class UnmanagedFileLoader
{
public const short FILE_ATTRIBUTE_NORMAL = 0x80;
public const short INVALID_HANDLE_VALUE = -1;
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint CREATE_NEW = 1;
public const uint CREATE_ALWAYS = 2;
public const uint OPEN_EXISTING = 3;
// Use interop to call the CreateFile function.
// For more information about CreateFile,
// see the unmanaged MSDN reference library.
[DllImport("kernel32.dll", SetLastError = true, CharSet=CharSet.Unicode)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
private SafeFileHandle handleValue = null;
public UnmanagedFileLoader(string Path)
{
Load(Path);
}
public void Load(string Path)
{
if (Path == null || Path.Length == 0)
{
throw new ArgumentNullException("Path");
}
// Try to open the file.
handleValue = CreateFile(Path, GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
// If the handle is invalid,
// get the last Win32 error
// and throw a Win32Exception.
if (handleValue.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
}
public SafeFileHandle Handle
{
get
{
// If the handle is valid,
// return it.
if (!handleValue.IsInvalid)
{
return handleValue;
}
else
{
return null;
}
}
}
}
使用 Windows API 访问文件日期
下面的GetFileTimeSample
类取自www.pinvoke.net使用另一个 Windows API 调用,特别是GetFileTime
. 此实现只是一个示例,您肯定能够对其进行调整以仅获取您需要的日期。以其当前形式,它将输出所有三个日期。
用法:
DateTime fileDateCreated;
DateTime fileDateAccessed;
DateTime fileDateModified;
GetFileTimeSample.GetFileTimes(path, out fileDateCreated, out fileDateAccessed, out fileDateModified);
从 C# 7.0 开始,可以out
直接在函数调用中声明变量,如下所示:
GetFileTimeSample.GetFileTimes(path, out DateTime fileDateCreated, out DateTime fileDateAccessed, out DateTime fileDateModified);
获取文件时间样本
public class GetFileTimeSample
{
private const uint GENERIC_READ = 0x80000000;
private const uint FILE_SHARE_READ = 0x1;
private const uint FILE_ATTRIBUTE_NORMAL = 0x80;
private const int INVALID_HANDLE_VALUE = -1;
private const uint OPEN_EXISTING = 3;
[StructLayout(LayoutKind.Sequential)]
private struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(
IntPtr hObject
);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr SecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetFileTime(
IntPtr hFile,
ref FILETIME lpCreationTime,
ref FILETIME lpLastAccessTime,
ref FILETIME lpLastWriteTime
);
public static void GetFileTimes(string FileName, out DateTime CreationTime, out DateTime LastAccessTime, out DateTime LastWriteTime)
{
CreationTime = DateTime.MinValue;
LastAccessTime = DateTime.MinValue;
LastWriteTime = DateTime.MinValue;
IntPtr ptr = IntPtr.Zero;
FILETIME ftCreationTime = new FILETIME();
FILETIME ftLastAccessTime = new FILETIME();
FILETIME ftLastWriteTime = new FILETIME();
try
{
ptr = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
if (ptr.ToInt32() == INVALID_HANDLE_VALUE)
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
if (GetFileTime(ptr, ref ftCreationTime, ref ftLastAccessTime, ref ftLastWriteTime) != true)
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
CreationTime = DateTime.FromFileTimeUtc((((long)ftCreationTime.dwHighDateTime) << 32) | ((uint)ftCreationTime.dwLowDateTime));
LastAccessTime = DateTime.FromFileTimeUtc((((long)ftLastAccessTime.dwHighDateTime) << 32) | ((uint)ftLastAccessTime.dwLowDateTime));
LastWriteTime = DateTime.FromFileTimeUtc((((long)ftLastWriteTime.dwHighDateTime) << 32) | ((uint)ftLastWriteTime.dwLowDateTime));
}
catch (Exception e)
{
throw (e);
}
finally
{
if (ptr !=IntPtr.Zero && ptr.ToInt32() != INVALID_HANDLE_VALUE) CloseHandle(ptr);
}
}
}