2018 EDIT: As indicated below and by other sources, targeting the Creator's Update or higher allows for read-only file access of a file opened for write by another process. Hooray!
I seem to have hit a brick wall when trying to develop a Windows Store app for the desktop. I'm trying to open a large (100+ MB) log file that another application has open and do real time processing on the latest events as they're written to the file.
With regular, non-sandboxed C#, this is pretty straightforward:
System.IO.FileStream stream = File.Open("LOGFILE PATH HERE", System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Unfortunately, in a UWP, I get "UnauthorizedAccessException" whenever I try to open a file that's in use by another app. I've tried every API in every combination I could find, but have had zero luck, so I've come here for some suggestions.
Some of what I've tried:
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();
Quick Repro:
Open a PowerShell window, and run this command to hold open "test.txt" in your home directory:
$f = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::Write, [System.IO.FileShare]::ReadWrite);
This is expected behavior for the Universal APIs as of the Anniversary Update. (aka RS1). The Windows.Storage.* APIs and streams use what is called a "Polite Reader" model. In this model readers can be interrupted by a writer, which generates the OPLOCK break errors. In RS1 this also means that readers are blocked if ANY open handle for write exists already.
In the Creators Update (aka RS2) some things are changing on this. As the Universal Platform evolved from the original WinRT with a single foreground app, the need to allow apps to use more traditional models arose. Thus, in RS2 we are making a few changes to help in this scenario.