有没有什么方法可以不使用try/catch块来检查文件是否被锁定?
现在,我所知道的唯一方法是打开文件并捕获任何System.IO.IOException。
有没有什么方法可以不使用try/catch块来检查文件是否被锁定?
现在,我所知道的唯一方法是打开文件并捕获任何System.IO.IOException。
当前回答
您还可以检查是否有任何进程正在使用此文件,并像安装程序一样显示必须关闭才能继续的程序列表。
public static string GetFileProcessName(string filePath)
{
Process[] procs = Process.GetProcesses();
string fileName = Path.GetFileName(filePath);
foreach (Process proc in procs)
{
if (proc.MainWindowHandle != new IntPtr(0) && !proc.HasExited)
{
ProcessModule[] arr = new ProcessModule[proc.Modules.Count];
foreach (ProcessModule pm in proc.Modules)
{
if (pm.ModuleName == fileName)
return proc.ProcessName;
}
}
}
return null;
}
其他回答
不,不幸的是,如果你仔细想想,这些信息无论如何都是毫无价值的,因为文件可能在下一秒就被锁定(阅读:短时间跨度)。
为什么您特别需要知道文件是否被锁定?知道了这一点,我们可能会以其他方式给你一些好的建议。
如果你的代码是这样的:
if not locked then
open and update file
然后,在这两行之间,另一个进程可以很容易地锁定文件,给您带来您一开始试图避免的相同问题:异常。
在Powershell中也是一样
function Test-FileOpen
{
Param
([string]$FileToOpen)
try
{
$openFile =([system.io.file]::Open($FileToOpen,[system.io.filemode]::Open))
$open =$true
$openFile.close()
}
catch
{
$open = $false
}
$open
}
然后,在这两行之间,另一个进程可以很容易地锁定文件,给您带来您一开始试图避免的相同问题:异常。
但是,通过这种方式,您将知道问题是暂时的,并稍后重试。(例如,您可以编写一个线程,如果在尝试写入时遇到锁,则会不断重试,直到锁消失。)
另一方面,IOException本身还不够特定,以至于锁定是导致IO失败的原因。可能有一些不是暂时的原因。
您可以通过尝试自己先读取或锁定文件来查看文件是否被锁定。
请在这里查看我的回答以了解更多信息。
我最后做的是:
internal void LoadExternalData() {
FileStream file;
if (TryOpenRead("filepath/filename", 5, out file)) {
using (file)
using (StreamReader reader = new StreamReader(file)) {
// do something
}
}
}
internal bool TryOpenRead(string path, int timeout, out FileStream file) {
bool isLocked = true;
bool condition = true;
do {
try {
file = File.OpenRead(path);
return true;
}
catch (IOException e) {
var errorCode = Marshal.GetHRForException(e) & ((1 << 16) - 1);
isLocked = errorCode == 32 || errorCode == 33;
condition = (isLocked && timeout > 0);
if (condition) {
// we only wait if the file is locked. If the exception is of any other type, there's no point on keep trying. just return false and null;
timeout--;
new System.Threading.ManualResetEvent(false).WaitOne(1000);
}
}
}
while (condition);
file = null;
return false;
}