我认为没有办法找到打开文件的进程而不进入 WinApi。至于检查它是否在使用中,你唯一能做的,就像你链接到状态的 SO 问题,就是将文件访问尝试包装在一个 try/catch 块中。
查找打开哪个文件的代码可能很难看,但可能有一个 API 可以很好地包装它。有 3rd 方实用程序会告诉您这一点(Unlocker是最著名的例子)。您还可以使用ProcessExplorer按文件名搜索打开的文件句柄。但是,这些并不能真正帮助您。
我试图在这里得到的简短回答是,您已经在已链接的 SO 问题中获得了问题第一部分的答案,而第二部分可能需要 WIN32 调用,这是您想要避免的,但是你可能不得不在 Win32 中弄脏你的手......仍然需要帮助吗?
编辑:您可以使用 sysinternals Handle实用程序。您需要获取该命令的输出并自己解析它。您可以像这样读取已执行进程的输出
string result = proc.StandardOutput.ReadToEnd();
问题是您将在第一次运行 Handle 实用程序时弹出许可协议。如果这是您希望部署的东西,更不用说整个许可问题......
如果你仍然感兴趣,我可以告诉你你会怎么做。
编辑:这是一个可运行的程序,它将找到任何具有文件打开句柄的程序的 exe 名称和 pid。我添加了评论,但如有必要可以进一步详细说明。我在这里使用正则表达式来解析输出,因为考虑到手头的任务,这最有意义。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ProcessStartInfo si = new ProcessStartInfo();
si.FileName = "handle.exe"; //name of the handle program from sysinternals
//assumes that its in the exe directory or in your path
//environment variable
//the following three lines are required to be able to read the output (StandardOutput)
//and hide the exe window.
si.RedirectStandardOutput = true;
si.WindowStyle = ProcessWindowStyle.Hidden;
si.UseShellExecute = false;
si.Arguments = "test.xlsx"; //this is the file you're trying to access that is locked
//these 4 lines create a process object, start it, then read the output to
//a new string variable "s"
Process p = new Process();
p.StartInfo = si;
p.Start();
string s = p.StandardOutput.ReadToEnd();
//this will use regular expressions to search the output for process name
//and print it out to the console window
string regex = @"^\w*\.EXE";
MatchCollection matches = Regex.Matches(s, regex, RegexOptions.Multiline);
foreach (var match in matches)
{
Console.WriteLine(match);
}
//this will use regex to search the output for the process id (pid)
//and print it to the console window.
regex = @"pid: (?<pid>[0-9]*)";
matches = Regex.Matches(s, regex, RegexOptions.Multiline);
foreach (var obj in matches)
{
Match match = (Match)obj; //i have to cast to a Match object
//to be able to get the named group out
Console.WriteLine(match.Groups["pid"].Value.ToString());
}
Console.Read();
}
}
}