2013-12-21 3 views
0

Фон:
В моем проекте мне нужно отсканировать свой сектор HDD по секторам. Я использую Pinvoke из Kernel32.dll. Размер жесткого диска - 160 ГБ (почти 312 000 000 LBA). Петля просматривает каждую итерацию 8000 секторов.SetFilePointer на C# внезапно прекратить работу

Проблема:
Какая-то образом, после сканирования 40000 секторов успешно, стеки цикла без движения, и я даже не могут завершить приложение, если я не буду отключать жесткий диск (это внешний носитель). Я знаю, что у моих медиа нет поврежденных секторов.

При настройке указателя на файл с помощью SetFilePointer файла Kernel32.dll я обращаю внимание на низкие и высокие значения для смещения, но смещение даже не достигает 1 ГБ, поэтому я думаю, что в этом нет ничего общего, но где-то иначе (я так думаю, но я не уверен, я совершенно новичок в этом Pinvoke).

Это мой следующий код:

public enum EMoveMethod : uint 
    { 
     Begin = 0, 
     Current = 1, 
     End = 2 
    } 

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    static extern int SetFilePointer(
     [In] SafeFileHandle hFile, 
     [In] int lDistanceToMove, 
     [In, Out] ref int lpDistanceToMoveHigh, 
     [In] EMoveMethod dwMoveMethod); 

    [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); 

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes, 
     int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero); 

    static public int BytesPerSector(int drive) 
    { 
     int driveCounter = 0; 
     try 
     { 
      ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive"); 
      foreach (ManagementObject queryObj in searcher.Get()) 
      { 
       if (driveCounter == drive) 
       { 
        var t = queryObj["BytesPerSector"]; 
        return int.Parse(t.ToString()); 
       } 
       driveCounter++; 
      } 
     } 
     catch (ManagementException) { return -1; } 
     return 0; 
    } 

    static public int GetTotalSectors(int drive) 
    { 
     int driveCount = 0; 
     try 
     { 
      ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive"); 
      foreach (ManagementObject queryObj in searcher.Get()) 
      { 
       if (driveCount == drive) 
       { 
        var t = queryObj["TotalSectors"]; 
        return int.Parse(t.ToString()); 
       } 
       driveCount++; 
      } 
     } 
     catch (ManagementException) { return -1; } 
     return -1; 
    } 

    static private byte[] DumpSector(string drive, int sector, int bytesPerSector) 
    { 
     const uint GENERIC_READ = 0x80000000; 
     const uint OPEN_EXISTING = 3; 

     byte[] buf = null; 
     try 
     { 
      SafeFileHandle handleValue = CreateFile(drive, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); 
      if (handleValue.IsInvalid) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } 
      long sec = (long)sector * (long)bytesPerSector; 
      buf = new byte[bytesPerSector]; 
      int read = 0, moveToHigh = (int)(sec >> 32); 
      int Res=SetFilePointer(handleValue, (int)(sec & 0xffffffff), ref moveToHigh, EMoveMethod.Begin); 
      if (Res == -1) { Console.WriteLine("ERROR: "); return null; } 
      if (ReadFile(handleValue, buf, bytesPerSector, out read, IntPtr.Zero)==0) 
      { 
       Console.WriteLine("ERROR: "); return null; 
      } 
      handleValue.Close(); 
     } 
     catch (Exception Ex) { Console.WriteLine("ERROR: {0}", Ex.Message); return null; } 
     return buf; 
    } 

    static void Scanner() 
    { 
     if (DRV == -1) { Console.WriteLine("ERROR: Please select drive using <A>+ drive index number."); return; } // error 
     const int BFB = 8000; 
     byte[] b = DumpSector(HDDs[DRV], MyOffset, BlockSize * BFB); 
     int Sec16 = 0, IntOff = 0, JMP = 0; 
     string DMP = ""; 
     long FF = ((long)MyOffset * BlockSize) + (IntOff * 16); 
     Console.Write("0x{0} ", FF.ToString("X10")); 
     for (int byt = 0; byt < b.Length; byt++) 
     { 
      DMP += (char)b[byt]; 
      Console.Write("{0} ", b[byt].ToString("X2")); 
      Sec16++; FF++; 
      if (Sec16 == 8) Console.Write(" "); 
      if (Sec16 == 16) 
      { 
       Console.Write(" {0}", DMP.Replace("\x07", "").Replace("\x08", "").Replace("\x0a", "").Replace("\x0d", "").Replace("\x09", "")); Console.WriteLine(); 
       DMP = ""; Sec16 = 0; IntOff++; JMP++; 
       if (JMP == 32) { JMP = 0; IntOff += 224; FF += 3584; byt += 3584; } 
       Console.Write("0x{0} ", FF.ToString("X10")); 
      } 
     } 
     Console.WriteLine("- End of scan -"); 
    } 

Программа консольное приложение для того, чтобы ускорив процесс.

+0

Попробуйте инкапсулировать код с помощью try..catch, чтобы вы могли поймать сообщение об ошибке. – Jade

+0

Я изменил код в DumpSector, но не исключение .... Он просто остановил работу ... – Xerix

+0

Очень сложно определить причину, если мы не знаем, с чего начать. но может быть, вы получаете доступ к некоторым защищенным областям, таким как пейджинговая память, используемая операционной системой или файлом операционной системы. попробуйте не читать эту область, когда находитесь в окнах. – Jade

ответ

0

Даже если вы неправильно использовали какой-либо API, ваша программа не просто остановилась. Это вряд ли будет ошибкой использования API.

Возможно, это аппаратная ошибка. Типичным симптомом являются не убивающие процессы. Процесс может быть убит только Windows, когда последний ожидающий ввода-вывода будет завершен. Драйвер диска ожидает завершения ввода-вывода, но диск никогда не отвечает (или только после длительного таймаута).

+0

Есть возможность установить тайм-аут для чтения аппаратного RAW на C#? – Xerix

+0

Я не знаю ничего подобного в Windows. (Это не проблема с C#.) Попробуйте на другом диске (он будет работать). Замените диск. – usr

+0

Вы правы, это проблема с мультимедиа ... Интересно, почему у меня не было никакой ошибки ... – Xerix

Смежные вопросы