2018 年编辑: 如下文和其他来源所述,以创作者更新或更高版本为目标允许对由另一个进程打开以供写入的文件进行只读文件访问。万岁!
在尝试为桌面开发 Windows 应用商店应用程序时,我似乎遇到了瓶颈。我正在尝试打开另一个应用程序已打开的大型(100+ MB)日志文件,并在将最新事件写入文件时对其进行实时处理。
对于常规的非沙盒 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);
最佳答案
自周年更新以来,这是通用 API 的预期行为。 (又名 RS1)。 Windows.Storage.* API 和流使用所谓的“礼貌读者”模型。在此模型中,读取器可以被写入器中断,从而生成 OPLOCK 中断错误。在 RS1 中,这也意味着如果已经存在任何用于写入的打开句柄,则读取器将被阻止。
在创意者更新(又名 RS2)中,一些事情正在发生变化。随着通用平台从具有单个前台应用程序的原始 WinRT 发展而来,出现了允许应用程序使用更多传统模型的需求。因此,在 RS2 中,我们进行了一些更改以帮助解决这种情况。
- Unmodified 有礼貌的读者将不会再在作家已经存在的情况下打开失败。但是,如果作者实际写入文件,读者仍然会获得 oplock 中断。
- 共享违规会直接显示给调用者,而不是被转换为拒绝访问。 (为了兼容性,此新行为在调用应用程序上受到限制,在应用程序的 list 中将 RS2 声明为测试平台)
- 有新的 StorageOpenOptions 可用,因此应用程序可以更改其代码以使用新选项来获得不涉及机会锁的行为,从而有效地选择退出 OpLock 行为。
关于c# - UWP - 如果另一个应用程序打开文件,则无法打开文件进行阅读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42308428/