c# - 用 C# 通过 Pinvoke 读取 DVD 的特定扇区

标签 c# file-io pinvoke

我正在使用 C# 直接从磁盘读取数据并调用 kernel32 ReadFile 方法。我只想读取特定扇区以节省时间,但 ReadFile 从第一个扇区读取到第 N 个扇区。如何根据我的选择只读自己的扇区?

    [StructLayout(LayoutKind.Sequential)]
    public struct OVERLAPPED
    {
        public uint Internal;
        public uint InternalHigh;
        public uint Offset;
        public uint OffsetHigh;
        public int hEvent;
    }

    [DllImport("kernel32", SetLastError = true)]
    static extern int CreateFile(string filename, uint desiredAccess, uint shareMode, IntPtr attributes, uint creationDisposition, uint flagsAndAttributes, IntPtr templateFile);

    [DllImport("kernel32", SetLastError = true)]
    public static extern Boolean CloseHandle(int handle);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern Boolean ReadFile(IntPtr hFile, Byte[] buffer, UInt32 BytesToRead, ref UInt32 BytedRead, OVERLAPPED OverLapped);
    static int EIGHT_K = 8192;
    static int FIVE_TWELVE_BYTES = 512;
    static uint GENERIC_READ = 0x80000000;
    static uint OPEN_EXISTING = 3;
    static uint FILE_SHARE_READ = 1;
    static uint FILE_SHARE_WRITE = 2;

    [STAThread]
    private void button1_Click(object sender, EventArgs e)
    {
        int fileHandle = 0;
        bool returnVal = true;

        try
        {
            // Open the device specified (Using the boot partition)
            string deviceName = @"\\.\f:";
            fileHandle = CreateFile(deviceName, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, (IntPtr)0, OPEN_EXISTING, 0,(IntPtr)0);
            if (fileHandle != -1)
            {
                Byte[] sector = new Byte[EIGHT_K];
                UInt32 bytesRead = (uint)EIGHT_K;
                OVERLAPPED ol = new OVERLAPPED();

                // Can't get a FileStream ctor to work so I am using Win32 API ReadFile
                bool worked = ReadFile((IntPtr)fileHandle, sector, (uint)EIGHT_K, ref bytesRead, ol);
                return;

            }
        }

        catch (Exception ex)
        {
            return;
        }
        finally
        {
            CloseHandle(fileHandle);
        }
        return;
    }

我想标记 DVD,直到需要原始 DVD 才能运行该程序。

最佳答案

您的 OVERLAPPED 结构声明得不好,并且在 64 位进程中不正确。但无论如何你都不需要它。您没有执行重叠 I/O。这也没关系,因为 ReadFile 的声明不正确。该函数需要一个指向 OVERLAPPED 结构的指针。您按值传递它。

无论如何,您都不需要考虑重叠 I/O。因此,通过从代码中删除 OVERLAPPED 结构声明来解决此问题。并像这样声明 ReadFile:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern Boolean ReadFile(IntPtr hFile, Byte[] buffer, 
    UInt32 BytesToRead, out UInt32 BytedRead, IntPtr Overlapped);

传递IntPtr.Zero作为Overlapped参数。并确保检查 ReadFile 的返回值是否有错误。

下一步是寻找文件中的位置。为此,请使用 SetFilePointerEx

DllImport("kernel32.dll")]
static extern bool SetFilePointerEx(IntPtr hFile, long liDistanceToMove,
   out long lpNewFilePointer, uint dwMoveMethod);

查阅 SetFilePointerEx 的文档找出如何调用这个函数。

由于您使用的是直接磁盘访问,因此您当然需要将读取与扇区边界对齐。

关于c# - 用 C# 通过 Pinvoke 读取 DVD 的特定扇区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24746540/

相关文章:

c++ - 使用 get() 从包括空格的输入中读取字符

C++: ifstream::getline 问题

c# - PInvoke,数据来回传输

c# - dotnet pack项目引用

c# - 尝试捕捉不起作用

c# - 重载方法签名 - 编译器将可空类型视为常规值类型的同义词

java - 是否有任何有效的方法来查找文件中特定 4 字节 block 的所有实例的第一个字节?

c++ - 编写 C++ Dll 并将其高效地公开给 .NET(不通过 C++/CLI)

c# - 使用 C# 为 PInvoke 字符串编码指定代码页

c# - 有哪些工具可用于测试多线程 .net 代码?