2017-02-17 17 views
2

Я, кажется, ударил кирпичную стену, пытаясь разработать приложение для Windows Store для рабочего стола. Я пытаюсь открыть большой файл журнала (100+ МБ), открытое другим приложением, и выполнять обработку в реальном времени на последних событиях, когда они записываются в файл.UWP - Не удается открыть файл для чтения, если другое приложение открыто.

При регулярном, неизолированные C#, это довольно просто:

System.IO.FileStream stream = File.Open("LOGFILE PATH HERE", System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 

К сожалению, в UWP, я получаю «UnauthorizedAccessException» всякий раз, когда я пытаюсь открыть файл, который находится в использовании другого приложения. Я пробовал каждый API в каждой комбинации, которую я мог найти, но имел нулевую удачу, поэтому я пришел сюда для некоторых предложений.

Некоторые из того, что я пробовал:

Windows.Storage.Pickers.FileOpenPicker picker = new Windows.Storage.Pickers.FileOpenPicker(); 
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.List; 
//Prompt the user to open the log file: 
Windows.Storage.StorageFile logFile = await picker.PickSingleFileAsync(); 
picker.FileTypeFilter.Add(".txt"); 

//This won't work in any case, because it doesn't use the handle that the user picked, 
// so the UWP sandboxing blocks it: 
new FileStream(logFile.Path, FileMode.OpenOrCreate, FileAccess.Read); 

//EDIT: These don't work if the file is open either, I must have made a mistake earlier 
await FileIO.ReadBufferAsync(logFile); 
await FileIO.ReadLinesAsync(logFile); 

//These work if the file is not open by another app, but fail if another app has the file open 
await logFile.OpenAsync(Windows.Storage.FileAccessMode.Read); 
await logFile.OpenStreamForReadAsync(); 

Быстрый Репро:

Открыть окно PowerShell и запустите эту команду, чтобы держать открытым "test.txt" в вашем домашнем каталоге:

$f = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::Write, [System.IO.FileShare]::ReadWrite); 
+0

Посмотреть это сообщение: http://stackoverflow.com/questions/4400517/how-can-i-read-a-file-even-when-getting-an-in-use-by-another-process -exception – Sparrow

+0

Это только для приложений, отличных от UWP, в этом случае это не сработает. Это первое, что я попробовал. Также у меня есть этот код в качестве примера того, что не работает в моем комментарии: * ( –

+0

Человек, это расстраивает .. согласно System.Diagnostics.Stopwatch, ReadBufferAsync занимает 100 мс, чтобы читать скромный файл журнала 100 МБ даже на моем SSD-оборудованная сверхбыстрая машина для разработчиков, поэтому я думаю, что это действительно буферизует весь файл. Между тем, в файлах, которые еще не открыты, метод OpenAsync (...) StorageFile занимает менее 2 мс, так что это именно то, что мне нужно Fiddlesticks !!! –

ответ

0

Я сделал простой тест, и он должен работать. Тест проходит следующим образом: - откройте файл.txt с помощью Блокнота, файл содержит только одну строку текста, - запустите приложение с кодом ниже, - выберите файл, который все еще открыт в «Блокноте», - вам следует см. в отладочном выводе первую строку и пустую секунду.

Код:

public async Task GetFile() 
{ 
    Windows.Storage.Pickers.FileOpenPicker picker = new Windows.Storage.Pickers.FileOpenPicker(); 
    picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.List; 
    picker.FileTypeFilter.Add(".txt"); 
    //Prompt the user to open the log file: 
    Windows.Storage.StorageFile logFile = await picker.PickSingleFileAsync(); 

    try 
    { 
     using (var stream = await logFile.OpenStreamForReadAsync()) 
     using (var reader = new StreamReader(stream)) 
     { 
      var line = await reader.ReadLineAsync(); 
      Debug.WriteLine($"The first line: {line} - waiting"); 
      await Task.Delay(10000); 
      line = await reader.ReadLineAsync(); 
      Debug.WriteLine($"The next line: {line} - waiting"); 
     } 
    } 
    catch (Exception exc) 
    { 
     Debug.WriteLine($"Exception {exc.Message}"); 
    } 
} 

Во втором тесте я изменил файл в блокноте и сохранил его, в то время как код выше хиты await Task.Delay(), то при попытке прочитать вторую строку, вы, вероятно, получите: 'Исключение Ручка, с которой был связан этот oplock, была закрыта. Теперь oplock сломан. '.

Я вижу, что вы не располагаете потоками, может быть, проблема здесь? Вы пытались использовать using для Idisposable?

+0

Спасибо Romasz. Я попробовал OpenStreamForReadAsync, и это не сработало. Я просто попробовал пример, который вы предоставили, и он работает для документа, который я открывал в «Блокноте», но если я его открываю с помощью другого приложения (или PowerShell), он выдает UnauthorizedAccessException , Я вроде как новичок в C#, хотя, как мне выполнить эту задачу? Я сделал обработчик событий кнопки и просто вызвал «ожидание GetFile()». Я отредактирую свое оригинальное сообщение, чтобы добавить команду powershell, которую я использовал для хранения открытого файла, что, похоже, дублирует поведение большого приложения регистрации. –

+0

@DebugArnaut Вы пробовали только с помощью другого приложения или powershell? Powershell отдельно или в визуальной студии? – Romasz

2

Ожидаемое поведение для универсальных API-интерфейсов с обновлением юбилея. (иначе RS1). API и потоки Windows.Storage. * Используют так называемую модель «Polite Reader». В этой модели читатели могут быть прерваны писателем, который генерирует ошибки прерывания OPLOCK. В RS1 это также означает, что читатели блокируются, если уже существует ANY open handle for write.

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

  1. Unmodified вежливы читатель больше не будет терпеть неудачу на открытой, если автор уже существует. Тем не менее, читатели будут по-прежнему получать перерывы oplock, если писатель действительно пишет в файл.
  2. Обмен Нарушения отображаются непосредственно вызывающему абоненту, а не переводятся в AccessDenied.(Для совместимости это новое поведение зашифровывается в вызывающем приложении, объявляющем RS2 в качестве тестируемой платформы в манифесте приложений)
  3. Доступны новые StorageOpenOptions, чтобы приложения могли изменять свой код, чтобы использовать новые параметры для получения поведения, которое не работает 't задействовать oplocks, эффективно отказываясь от поведения OpLock.

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

  • Нет связанных вопросов^_^