1

我使用 C# .NET ,与 2008 , .net 3.5

对我来说,这很困难,但我需要 C# 中的示例代码:

  1. 检查文件或文件夹是否正在使用

  2. 如果文件或文件夹正在使用中,则使用它的进程的名称

例如,在我的问题中。

我尝试删除文件,我得到“该进程无法访问文件'XYZ',因为它正在被另一个进程使用。” 例外。

File.Delete(infoFichero.Ruta);

我想检查一个文件是否正在使用,以及使用它的进程的名称。

我需要示例代码,请提供源代码。我不想使用 c++,我不知道 c、c++、非托管代码或 WinApi。我只想使用 C# 代码(托管代码 .net)。

我已经阅读了几篇参考资料,但没有获得示例代码源,

如何检查文件是否正在使用?

当文件被锁定时,在 C# 中模拟等待 File.Open

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/9dabc172-237a-42db-850e-ada08885a5d5

如何检查文件是否正在使用?

读取被另一个应用程序锁定的文本文件的最简单方法

使用 C# 是否可以测试文件是否持有锁

编辑:来自严军 - MSFT

  string path = "D:\\temp2.xlsx";
            foreach (Process c in Process.GetProcesses()) {

                if (c.MainWindowTitle.Contains(Path.GetFileName(path))){
                    MessageBox.Show(c.ProcessName);
                    return;
                }
            }

            try{
                FileInfo f = new FileInfo(path);

                f.Delete();
            }
            catch (Exception ex){

                MessageBox.Show(ex.Message);
            }

...但是很难找到所有 100% 问题的解决方案。

  1. 如果 c.MainWindowTitle == null 或不包含文件名,则会出现问题。

  2. 另一台机器、PC、服务器等共享文件夹的问题,例如:

File.Delete(@\desiis\TEmporal\Project\script.targets);

任何示例代码,我都向专家、MVP、任何人寻求帮助。

更新:文件夹的相同问题

4

3 回答 3

3

我认为没有办法找到打开文件的进程而不进入 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();
        }
    }
}
于 2010-07-15T18:41:07.950 回答
1

没有纯粹的管理方法可以做到这一点。您必须通过 P/invoke 或类似的方式使用一些低级 API。

这里有关于如何做到这一点的好信息,但它是 C++ 代码。您必须自己进行移植。

http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx

请注意,这有一些复杂的问题,即围绕内核与用户空间内存的问题。这不是您要解决的简单问题。

于 2010-07-15T18:42:44.763 回答
0

试试 windows 进程资源管理器:

http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

不会让你从代码中做到这一点,但至少你可以弄清楚你的锁的来源是什么。

于 2010-07-15T18:52:13.883 回答