有关使用中的文件或文件夹的问题:获取使用文件或文件夹的另一个进程的名称

发布于 2024-09-10 05:55:35 字数 2107 浏览 5 评论 0原文

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

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

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

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

例如,在我的问题中。

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

File.Delete(infoFichero.Ruta);

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

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

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

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

模拟等待 File.Open 在 C# 文件时已锁定

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 或任何人寻求帮助。

更新:文件夹存在同样的问题

I using C# .NET , vs 2008 , .net 3.5

For me, is difficult, but I need sample code in C# for this:

  1. Check if a file or a folder is in use

  2. If file or a folder is in use, the name of Process that use it

For example, in my issue.

I try delete file, and I get "The process cannot access the file 'XYZ' because it is being used by another process." Exception.

File.Delete(infoFichero.Ruta);

I want check if a file is in use, and the name of Process that use it.

I need sample code, source code, please. I dont want use c++, I dont know c, c++, unmanaged code, or WinApi. I want use only C# code (managed code .net).

I have read several references but not get sample code source,

How to check if a file is in use?

Emulate waiting on File.Open in C# when file is locked

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

How to check if a file is in use?

Easiest way to read text file which is locked by another application

Using C# is it possible to test if a lock is held on a file

EDIT:
From Yan Jun - 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);
            }

...
But it is difficult get solution for all 100% issues.

  1. Problem if c.MainWindowTitle == null or not contains filename.

  2. Problem for shared folder in another machine, PC, server,... like:

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

any sample code, I ask for help gurus, MVPs, anyone.

UPDATE: the same issue for a folder

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

白鸥掠海 2024-09-17 05:55:35

我认为,如果不进入 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();
        }
    }
}

There's not going to be a way to find the process that has the file opened without stepping into the WinApi, I don't think. And as far as checking whether its in use, the only thing you can really do, as the SO questions you linked to state, is to wrap the file access attempts in a try/catch block.

The code to find which file has it opened is likely to be ugly, but there may be an API out there that wraps this up nicely. There are 3rd party utilities that will tell you this (Unlocker being the best known example). You can also use ProcessExplorer to search for open file handles by the filename. Those don't really help you though.

The short answer of what I'm trying to get across here is you have the answer for the first part of your question in the SO questions you already linked, and the second part would probably require WIN32 calls, which you want to avoid, but you're probably going to have to get your hands dirty in Win32... Still want help?

EDIT: You could shell out to sysinternals Handle utility. You would need to get the output of that command and parse it yourself. You can read the executed process's output like this

string result = proc.StandardOutput.ReadToEnd();

The issue with this is you're going to get a license agreement popup the first time you run the Handle utility. Not to mention the whole licensing issues if this is something you hope to deploy...

If you're still interested, I can show you how you'd go about this.

EDIT: Here's a runnable program that will find the exe name and pid of any program that has an open handle to a file. I added comments, but can elaborate further if necessary. I use Regular Expressions here to parse the output as that makes the most sense given the task at hand.

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();
        }
    }
}
烟柳画桥 2024-09-17 05:55:35

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

这里有关于实现此操作的方法的良好信息,但它是 C++ 代码。您必须自己进行移植。

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

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

There is no purely managed way to do this. You have to use some low-level APIs through P/invoke or similar.

There's good information here on a way to do it, but it's C++ code. You'd have to do the porting yourself.

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

Note there are some complex issues with this, namely the issues around kernel vs. userspace memory. This is not a simple problem you're trying to solve.

骄兵必败 2024-09-17 05:55:35

尝试 Windows Process Explorer:

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

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

Try the windows Process Explorer:

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

Won't let you do it from code, but at least you can figure out what the source of your locks are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文