2015-03-06 3 views
4

Есть ли какой-либо класс в .NET framework, который обеспечивает доступ к пути \. \ G: -. (то есть сырых объемов)?Доступ к файлу низкого уровня с .NET

В настоящее время мы делаем это без проблем, используя p/invoked ReadFile и WriteFile, что не является сложным для синхронного доступа, но утомительно добавлять async read/write из-за всей заботы, которую вам нужно взять на себя и обрабатывая структуру OVERLAPPED и управляя временем жизни объекта события и т. д. (т. е. все утомительные вещи, которые мы должны были бы сделать в коде Win32 ...)

Трудно доказать, что у вас есть взаимодействие с GC правильно, с любой простой методикой тестирования.

Класс FileStream содержит, без сомнения, весь этот код, абсолютно безупречный и изысканный, и использует множество внутренних помощников, которые мы не можем использовать. К сожалению, FileStream явно останавливает открытие исходного тома, поэтому мы не можем его использовать.

Есть ли что-нибудь еще в рамках, которое помогает избежать написания такого кода с нуля? Я проговорил в Reference Source, но ничего не выскочит.

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

System.IO.IOException: The parameter is incorrect. 

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
at System.IO.FileStream.SeekCore(Int64 offset, SeekOrigin origin) 
at System.IO.FileStream..ctor(SafeFileHandle handle, FileAccess access, Int32 bufferSize, Boolean isAsync) 
at OurApp.USBComms.UsbDevice..ctor(Char driveLetter) in 

Для справки, наш CreateFile вызов выглядит следующим образом:

var deviceName = String.Format(@"\\.\{0}:", driveLetter); 

var handle = SafeNativeMethods.CreateFile(deviceName, 
    0x80000000 | 0x40000000, 
    FileShare.ReadWrite, 
    0, 
    FileMode.Open, 
    (uint)FileOptions.Asynchronous | 0x20000000, // Last option is  'FILE_FLAG_NO_BUFFERING' 
    IntPtr.Zero); 
    if (handle.IsInvalid) 
    { 
     throw new IOException("CreateFile Error: " + Marshal.GetLastWin32Error()); 
    } 

Update3: оказывается, что (по объему ручки, во всяком случае), вы не можете назвать SetFilePointer на ручке, который был открыт с FILE_FLAG_OVERLAPPED. Это имеет смысл, поскольку SetFilePointer бесполезен в файлах, где есть какой-либо многопоточный доступ. К сожалению, FileStream, по-видимому, решил назвать это во время строительства по какой-либо причине (по-прежнему пытается отследить почему), что и является причиной сбоя.

+0

Дайте мне отдохнуть! Является ли этот вопрос сейчас вне темы на SO? Я прошел через зеркало? –

+0

Я не думаю, что это не по теме. Возможно, близкий избиратель запутался в этом * Есть ли что-то еще в рамках, которое помогает избежать написания такого кода с нуля?* –

+0

@WillDean Именно поэтому SO обречен. Люди здесь сейчас _bots_. Вы не можете сказать «привет» в вопросе или спросить что-то, не публикуя кучу кода, не опускаясь в ад. Грустно, но верно:/ – ken2k

ответ

2

Я считаю, что вы можете использовать этот constructor of FileStream, передавая предварительно открытый FileHandle как экземпляр SafeFileHandle. При этом вам удалось выполнить экземпляр FileStream, который вы можете использовать для выдачи операции асинхронного ввода-вывода.

public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync); 

Кроме того, когда вы планируете сделать асинхронную I/O, не забудьте установить флаг isAsnc истину. В противном случае you'll not get all the benefits of async I/O.

+0

Да, мы действительно пытались использовать этот подрывный подход, но FileStream затем испытывает ошибку «плохого параметра» где-то внутри него , когда он пытается сделать что-то неуместное с этим дескриптором. –

+0

@WillDean Можете ли вы дать мне более подробную информацию о том, где он взрывается с этой ошибкой? Может быть, мы делаем что-то еще неправильно? –

+0

Я добавил к OP со стеком-трассировкой, где он проходит, когда мы передаем дескриптор - я собираюсь пойти и дважды проверить качество обрабатываемого дескриптора, хотя, если вы думаете, что это должно работать –

3

Как отметил Шрирам Сактивель (+1), вы можете передать SafeFileHandle в конструктор FileStream.

Из вашего stacktrace Я предполагаю, что вы пытались найти поток в недопустимой позиции; Необработанные диски/объем имеют специальные правила относительно позиций чтения/записи.

Например, вы не можете начать чтение диска в середине сектора (вам нужно будет прочитать/искать на кусок 512 байт). Попробуйте прочитать, например, со смещением 0, чтобы убедиться, что он работает лучше.

+0

Я предполагаю, что правила указаны в [SetFilePointer] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365541 (v = vs.85) .aspx) применяются ... – rene

+0

Вы, вероятно, правильно о проблеме выравнивания - мы бережно относимся к этому в нашем существующем коде. Проблема в том, что * я * не пытаюсь найти его где угодно - этот вызов поступает из ctor класса FileStream. –

+0

@WillDean Это конструктор, пытающийся найти источник потока для вас, но я не знаю, почему он реализован таким образом, потому что если дескриптор асинхронный, это не имеет смысла (если только я чего-то не хватает) , – ken2k