Фон:
В моем проекте мне нужно отсканировать свой сектор 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 -");
}
Программа консольное приложение для того, чтобы ускорив процесс.
Попробуйте инкапсулировать код с помощью try..catch, чтобы вы могли поймать сообщение об ошибке. – Jade
Я изменил код в DumpSector, но не исключение .... Он просто остановил работу ... – Xerix
Очень сложно определить причину, если мы не знаем, с чего начать. но может быть, вы получаете доступ к некоторым защищенным областям, таким как пейджинговая память, используемая операционной системой или файлом операционной системы. попробуйте не читать эту область, когда находитесь в окнах. – Jade