2018 EDIT: 如下所示和其他来源,以Creator的更新或更高版本为目标,允许对另一个进程打开以供写入的文件进行只读文件访问 . 万岁!
在尝试为桌面开发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();
Quick Repro:
打开PowerShell窗口,然后运行此命令以在主目录中保持打开“test.txt”:
$f = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::Write, [System.IO.FileShare]::ReadWrite);
2 回答
这是周年纪念更新中Universal API的预期行为 . (又名RS1) . Windows.Storage . * API和流使用所谓的“礼貌读者”模型 . 在此模型中,读取器可能会被写入器中断,从而生成OPLOCK中断错误 . 在RS1中,这也意味着如果已存在任何打开的写入句柄,则会阻止读者 .
在创作者更新(又名RS2)中,有些事情正在发生变化 . 随着通用平台从最初的WinRT发展而来,只需一个前台应用程序,就需要允许应用程序使用更传统的模型 . 因此,在RS2中,我们进行了一些更改以帮助在这种情况下 .
如果作家已经存在, Unmodified 礼貌读者将不再在打开时失败 . 但是,如果编写器实际写入文件,读者仍将获得oplock中断 .
共享冲突直接显示给调用者,而不是转换为AccessDenied . (为了兼容性,这个新行为在调用应用程序上被门控,声明RS2作为应用程序清单中的测试平台)
有新的StorageOpenOptions可用,以便应用程序可以更改其代码以使用新选项来获取不涉及oplock的行为,从而有效地选择退出OpLock行为 .
我做了一个简单的测试,它应该工作 . 测试结果如下: - 使用记事本打开file.txt,文件只包含一行文本, - 使用下面的代码运行应用程序, - 选择仍在记事本中打开的文件, - 您应该在调试输出中看到第一行,第二行 .
代码:
在第二个测试中,我在记事本中修改了文件并将其保存,而上面的代码命中
await Task.Delay()
,然后在尝试读取第二行时,您可能会得到:'Exception与此oplock关联的句柄已关闭 . oplock现在坏了 . '我看到你没有处理流,也许问题在这里?您是否尝试过
using
用于Idisposable?