2016-08-03 15 views
0

У меня проблема с функциями kernal32 Pinvoke, поскольку они продолжают бросать INVALID_FILE_HANDLE. Программа считывает первый сектор текущего жесткого диска. Я не вижу, что не так в следующем коде.C# Pinvoke неверный дескриптор файла

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 (что указывает на то, что он не прошел). Чтобы определить, что пошло не так, вы должны позвонить GetLastWin32Errorнепосредственно послеCreateFile.
Когда вы вызываете его после попытки прочитать, ошибка, конечно, ERROR_INVALID_HANDLE (6), поскольку вы передали недействительный дескриптор на ReadFile.

Если вы звоните GetLastWin32Error сразу после провала попытки CreateFile вы получите сообщение об ошибке 2:

Система не может найти указанный файл.

Это происходит потому, что имя диска пропускает :

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

Я пытался с этим именем диска, но затем получил ошибку 32:

Процесс не может получить доступ к файлу, так как он используется другим процессом.

Я постоянно пытаюсь выяснить, как это может быть обработан ...