使用.NET进行低级别文件访问

本文关键字:文件 访问 NET 使用 | 更新日期: 2024-10-24 00:37:17

.NET框架中是否有提供''访问权限的类。''G: -样式路径。(即原始体积)?

我们目前使用p/invoked ReadFile和WriteFile来完成这项工作没有任何问题,这对于同步访问来说并不复杂,但添加异步读/写是很乏味的,因为你需要小心地固定和处理OVERLAPPED结构以及管理事件对象生存期等。(即,我们在Win32代码中必须做的所有乏味的事情…)

用任何简单的测试技术都很难证明你与GC的交互是正确的。

毫无疑问,FileStream类以一种完全防炸弹和精致的方式包含了所有这些代码,并利用了许多我们无法使用的内部助手。不幸的是,FileStream明确地阻止您打开原始卷,因此我们无法使用它。

框架中还有其他东西可以帮助避免从头开始编写这种代码吗?我在参考资料中翻了一下,但什么也没跳出来。

更新-我们已经尝试了下面的建议,通过自己打开设备并传入句柄来避免对路径类型的检查。当我们尝试此操作时,它会出现以下错误(请注意,此跟踪通过FileStream的构造函数,即我们根本没有机会与流交互):

System.IO.IOException: The parameter is incorrect.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.SeekCore(Int64 offset, SeekOrigin origin)
at System.IO.FileStream..ctor(SafeFileHandle handle, FileAccess access, Int32 bufferSize, Boolean isAsync)
at OurApp.USBComms.UsbDevice..ctor(Char driveLetter) in 

作为参考,我们的CreateFile调用如下所示:

var deviceName = String.Format(@"''.'{0}:", driveLetter);
var handle = SafeNativeMethods.CreateFile(deviceName,
     0x80000000 | 0x40000000,
     FileShare.ReadWrite,
     0,
     FileMode.Open,
     (uint)FileOptions.Asynchronous | 0x20000000, // Last option is       'FILE_FLAG_NO_BUFFERING'
     IntPtr.Zero);
     if (handle.IsInvalid)
     {
        throw new IOException("CreateFile Error: " + Marshal.GetLastWin32Error());
     }

Update3:事实证明(无论如何,在卷句柄上),您不能在用FILE_FLAG_OVERLAPPED打开的句柄上调用SetFilePointer。这是有道理的,因为SetFilePointer对任何类型的多线程访问的文件都是无用的。不幸的是,FileStream似乎出于某种原因(仍在努力找出原因)决定在构建过程中调用此函数,这就是导致失败的原因。

使用.NET进行低级别文件访问

正如Sriram Sakthvel所指出的(+1),您可以将SafeFileHandle传递给FileStream构造函数。

从你的堆栈中,我假设你试图将流搜索到一个无效的位置;原始磁盘/卷具有关于读/写位置的特殊规则。

例如,您无法开始读取扇区中间的磁盘(您必须读取/查找512字节的每个块)。例如,请尝试在偏移量0处读取,看看它是否工作得更好。

我相信您可以使用FileStream的这个构造函数将预先打开的FileHandle作为SafeFileHandle实例传递。有了它,您就管理了FileStream实例,可以使用它来发布异步I/O操作。

public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync);

另外,当您计划执行异步I/O时,不要忘记将isAsnc标志设置为true。否则,您将无法获得异步I/O的所有好处。