如何在C#中获取进程的打开文件句柄列表?

43
如何在C#中按进程ID获取打开文件句柄列表?我想深入挖掘并获取文件名。寻找等效于进程资源管理器所做的编程方法。很可能需要使用Interop。考虑对此进行悬赏,实现过程相当复杂。

3
对于那些偶然发现这个帖子的人,@manuc66提供的答案最终对我起作用了。但是,这里提供的实现针对x86平台。我已经分叉了该仓库并进行了一些调整,使其可以在x86和x64上运行。您可以在此处找到修改后的实现: https://github.com/urosjovanovic/MceController/blob/master/VmcServices/DetectOpenFiles.cs - urosjovanovic
7个回答

25

哎呀,这个从托管代码中完成会很困难。

在codeproject上有一个示例

大部分的工作可以通过Interop来完成,但你需要一个驱动程序来获取文件名,因为它位于内核的地址空间。Process Explorer将驱动程序嵌入了其资源中。从C#进行所有连接并支持64位和32位,将是非常头痛的。


1
谁在意代码,那个东西很有用!它所做的事情甚至比进程资源管理器还要好。 - Brian
这在托管代码中并不容易,如果我必须构建类似的东西,我可能会简单地调用一个C++程序。@Kiquenet - Sam Saffron

12

看看这个文件: http://vmccontroller.codeplex.com/SourceControl/changeset/view/47386#195318

然后使用:

DetectOpenFiles.GetOpenFilesEnumerator(processID);

演示:

using System;
using System.Diagnostics;

namespace OpenFiles
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var openFiles = VmcController.Services.DetectOpenFiles.GetOpenFilesEnumerator(Process.GetCurrentProcess().Id))
            {
                while (openFiles.MoveNext())
                {
                    Console.WriteLine(openFiles.Current);
                }
            }
            Console.WriteLine();
            Console.ReadKey();
        }
    }
}

它依赖于程序集 System.EnterpriseServices


按照您提到的方式运行它,GetOpenFilesEnumerator将返回一个具有2个成员的对象:<br>ERROR_ACCESS_DENIED和ERROR_INVALID_PARAMETERS。 - Lucian
刚刚测试了一下,这段代码运行正常。也许你实际上没有权限访问。 - Mehran
你知道“EventTrackingEnabledAttribute”或“ServicedComponent”需要哪些汇编吗? - Entree
1
@MacGyver System.EneterpriseServices - dwkd
VmcController不再在System.EnterpriseServices中,我无法编译它。我需要包含这个文件https://github.com/gjniewenhuijse/MceController/blob/master/VmcServices/DetectOpenFiles.cs。感谢Gert-Jan Niewenhuijse,这显然是Microsoft Visual Media Controoer的一个副项目。我正在使用它来关闭已关闭但未被遗忘的办公文件。 - dr d b karron
它总是产生一个溢出异常。 - daniol

12

您还可以运行由Mark Rusinovich创建的命令行应用程序Handle, 并解析输出。


4
为什么选择@bruce?有任何原因吗? - Kiquenet
4
使用Handle工具唯一的真正问题是它的许可证——你无法分发Handle,即使是在免费软件中也不行。 - penderi
Handle.exe是一个32位应用程序,对吧?因此,您无法轻松地从64位C#应用程序中启动它。 - seveves
有Handle64.exe也在@seveves。 - Ultimate Luki

11

好东西。我会看看能否让互操作性起作用。 - Sam Saffron

2
请查看wj32的Process Hacker 1版本,可以完成您所需的功能,还有更多功能。

2

Handle是一款很棒的程序,链接到codeproject也不错。

@Brian 代码的原因是handle.exe不可再分发,他们也没有发布源代码。

看起来在.Net中不容易做到这一点,因为需要嵌入式设备驱动程序才能访问信息。这在typical .net 编程中无法完成,需要使用非托管DLL。与typical .net编程相比,它涉及相对较深的内核代码。我很惊讶WMI没有暴露这个功能。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接