2016-08-03 70 views
0

我遇到了kernal32 Pinvoke函数的问题,因为它们会一直抛出INVALID_FILE_HANDLE。该程序读取当前硬盘的第一个扇区。我看不到以下代码有什么问题。C#拼写无效的文件句柄

class Program 
    { 
    const uint GENERIC_READ = 0x80000000; 
    const uint FILE_SHARE_READ = 0x00000001; 
    const uint OPEN_EXISTING = 0x00000003; 
    const uint FILE_FLAG_DELETE_ON_CLOSE = 0x04000000; 

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern SafeFileHandle CreateFile(string Disk, uint Access, uint ShareMode, IntPtr SecurityAttributes, uint CreationDisposition, uint Flags, IntPtr TemplateFile); 
    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern uint SetFilePointer([In] SafeFileHandle Handle, [In] int DistanceToMove, [Out] out int DistanceToMoveHigh, [In] int MoveMethod); 
    [DllImport("kernel32.dll", SetLastError = true)] 
    unsafe public static extern int ReadFile(SafeFileHandle Handle, [Out] byte[] Buffer, int NumberOfBytesToRead, out int NumberOfBytesRead, IntPtr Overlapped); 



    unsafe public static void Main(string[] args) 
    { 
     string Drive = @"\\.\C"; 
     int SectorSize = 512; 
     int Sector = 0; 
     int BytesRead, DistanceToMoveHigh; 
     byte[] Buffer = new byte[SectorSize]; 

     SafeFileHandle Handle = CreateFile(Drive, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, IntPtr.Zero); 
     SetFilePointer(Handle, Sector * SectorSize, out DistanceToMoveHigh, 0); 
     ReadFile(Handle, Buffer, SectorSize, out BytesRead, IntPtr.Zero); 

     Console.WriteLine(Marshal.GetLastWin32Error()); // It gives 6 which translates to an INVALID_FILE_HANDLE error 
     Console.ReadKey(); 
    } 
} 

回答

2

您致电CreateFile失败。当然你不知道,因为你省略了错误检查。阅读文档。您调用的所有三个函数的错误均由返回值发出信号。你忽略的是什么。

您致电CreateFile返回INVALID_HANDLE_VALUE。你需要为此进行测试。当你遇到这种情况,只有这样,请致电GetLastWin32Error。那么可能会返回ERROR_ACCESS_DENIED

  • 通过FILE_FLAG_DELETE_ON_CLOSE是一个错误。删除该标志。
  • 我相信共享标志必须是FILE_SHARE_READ | FILE_SHARE_WRITE
  • 文件名必须为@"\\.\C:"并带有尾部冒号。
  • 而且您将需要将该进程升级执行。
0

您以错误的方式使用GetLastWin32Error

这里失败的方法是CreateFile并返回INVALID_HANDLE_VALUE(表示失败)。要确定出了什么问题,您必须在CreateFile之后直接拨打GetLastWin32Error
当您尝试读取后调用它时,当您将无效句柄传递给ReadFile时,错误当然是ERROR_INVALID_HANDLE (6)

如果失败CreateFile后直接致电GetLastWin32Error你会得到错误2:

该系统找不到指定的文件。

这是因为驱动器名称错过了:

string Drive = @"\\.\C:"; // <- add colon : 

我与驱动器名称试过,但后来得到了错误32:

该进程无法访问该文件,因为它正在被另一个进程使用。

我一直试图弄清楚如何处理...