UWP - 如果其他应用程序打开文件,则无法打开文件
尝试为桌面开发Windows应用商店应用程序时,我似乎遇到了困难。我试图打开另一个应用程序已打开的大型(100+ MB)日志文件,并在写入文件时对最新事件进行实时处理。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);
我做了一个简单的测试,它应该工作。测试如下: - 用记事本打开一个file.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()
,然后试图读取第二行的时候,你可能会得到: '异常与此关联的手柄已关闭。这块手表现在坏了。'。
我看到你没有处理流,也许问题出在这里?您是否尝试过使用using
作为Idisposable?
感谢Romasz。我尝试了OpenStreamForReadAsync,并且它不起作用我刚刚试用了你提供的例子,它对我在记事本中打开的文档起作用,但是如果我使用另一个应用程序(或PowerShell)将其打开,它将引发UnauthorizedAccessException 。 虽然我是一个C#新手,我该如何执行该任务?我创建了一个按钮事件处理程序,并将其命名为“await GetFile()”。 我会编辑我的原始帖子,添加我用来保存打开的文件的powershell命令,这似乎重复了大型日志记录应用程序的行为。 –
@DebugArnaut您是否尝试过使用其他应用程序或PowerShell? Powershell独立或在视觉工作室? – Romasz
这是周年纪念更新通用API的预期行为。 (又名RS1)。 Windows.Storage。* API和流使用所谓的“有礼读者”模式。在这个模型中,读者可以被作家打断,这会产生OPLOCK中断错误。在RS1中,这也意味着如果已经存在任何用于写入的打开句柄,则读取器被阻止。
在创作者更新(又名RS2)中,有些事情正在改变。随着通用平台从最初的WinRT演变为单一的前台应用程序,需要允许应用程序使用更传统的模型。因此,在RS2中,我们正在做一些改变来帮助解决这种情况。
- 的未修改有礼貌阅读器将不再开放失败,如果一个作家已经存在。但是,如果作者实际写入文件,读者仍然会得到oplock中断。
- 共享冲突直接显示给调用者,而不是翻译成AccessDenied。(为了兼容性,这种新行为在呼叫应用程序上被屏蔽,声明RS2是应用程序清单中的测试平台)
- 有新的StorageOpenOptions可用,因此应用程序可以更改其代码以使用新选项来获取行为不涉及oplocks,有效地选择OpLock行为。
看到这篇文章:http://stackoverflow.com/questions/4400517/how-can-i-read-a-file-even-when-getting-an-in-use-by-another-process -exception – Sparrow
这只适用于非UWP应用程序,在这种情况下它不起作用。这是我尝试的第一件事。还有,我的代码作为一个例子,说明什么在我的评论中不起作用:*( –
Man,这令人沮丧..根据System.Diagnostics.Stopwatch,即使在我的系统上,ReadBufferAsync也需要100ms才能读取一个适中的100MB日志文件同时,对于尚未打开的文件,StorageFile的OpenAsync(...)方法需要2ms以下的时间,所以它正是我需要的。Fiddlesticks !!! –