获取当前在进程C#中加载的DLL列表

时间:2016-04-05 15:49:03

标签: c# dll

在Process Explorer中,我可以查看所选进程加载的所有dll(和dll详细信息)。怎么能这样编程?

我可以获得这样的具体流程详情。但不确定从哪里开始?

Process[] processlist = Process.GetProcesses();

foreach(Process theprocess in processlist){
Console.WriteLine(“Process: {0} ID: {1}”, theprocess.ProcessName, theprocess.Id);
}

enter image description here

4 个答案:

答案 0 :(得分:6)

存在Process.Modules属性,您可以枚举该进程加载的所有模块(exe和.dll)。

foreach (var module in proc.Modules) { Console.WriteLine(string.Format("Module: {0}", module.FileName)); }

根据ProcessModule类,它为您提供特定模块的属性。

答案 1 :(得分:5)

运行64位进程并尝试从32位进程收集所有模块时,Process.Modules解决方案是不够的。默认情况下,64位仅适用于64位进程,32位仅适用于32位进程。

对于适用于“AnyCPU”,“x86”和“x64”的解决方案,只需使用目标进程调用CollectModules函数,请参阅下文。注意:无法从32位进程收集64位模块。

public List<Module> CollectModules(Process process)
{
        List<Module> collectedModules = new List<Module>();

        IntPtr[] modulePointers = new IntPtr[0];
        int bytesNeeded = 0;

        // Determine number of modules
        if (!Native.EnumProcessModulesEx(process.Handle, modulePointers, 0, out bytesNeeded, (uint)Native.ModuleFilter.ListModulesAll))
        {
            return collectedModules;
        }

        int totalNumberofModules = bytesNeeded / IntPtr.Size;
        modulePointers = new IntPtr[totalNumberofModules];

        // Collect modules from the process
        if (Native.EnumProcessModulesEx(process.Handle, modulePointers, bytesNeeded, out bytesNeeded, (uint)Native.ModuleFilter.ListModulesAll))
        {
            for (int index = 0; index < totalNumberofModules; index++)
            {
                StringBuilder moduleFilePath = new StringBuilder(1024);
                Native.GetModuleFileNameEx(process.Handle, modulePointers[index], moduleFilePath, (uint)(moduleFilePath.Capacity));

                string moduleName = Path.GetFileName(moduleFilePath.ToString());
                Native.ModuleInformation moduleInformation = new Native.ModuleInformation();
                Native.GetModuleInformation(process.Handle, modulePointers[index], out moduleInformation, (uint)(IntPtr.Size * (modulePointers.Length)));

                // Convert to a normalized module and add it to our list
                Module module = new Module(moduleName, moduleInformation.lpBaseOfDll, moduleInformation.SizeOfImage);
                collectedModules.Add(module);
            }
        }

        return collectedModules;
    }
}

public class Native
{
    [StructLayout(LayoutKind.Sequential)]
    public struct ModuleInformation
    {
        public IntPtr lpBaseOfDll;
        public uint SizeOfImage;
        public IntPtr EntryPoint;
    }

    internal enum ModuleFilter
    {
        ListModulesDefault = 0x0,
        ListModules32Bit = 0x01,
        ListModules64Bit = 0x02,
        ListModulesAll = 0x03,
    }

    [DllImport("psapi.dll")]
    public static extern bool EnumProcessModulesEx(IntPtr hProcess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] IntPtr[] lphModule, int cb, [MarshalAs(UnmanagedType.U4)] out int lpcbNeeded, uint dwFilterFlag);

    [DllImport("psapi.dll")]
    public static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] uint nSize);

    [DllImport("psapi.dll", SetLastError = true)]
    public static extern bool GetModuleInformation(IntPtr hProcess, IntPtr hModule, out ModuleInformation lpmodinfo, uint cb);
}

public class Module
{
    public Module(string moduleName, IntPtr baseAddress, uint size)
    {
        this.ModuleName = moduleName;
        this.BaseAddress = baseAddress;
        this.Size = size;
    }

    public string ModuleName { get; set; }
    public IntPtr BaseAddress { get; set; }
    public uint Size { get; set; }
}

答案 2 :(得分:1)

这取决于你想要的东西。

获取加载到特定应用程序域的.NET程序集列表很简单(AppDomain.GetAssemblies)。

但是,在一个过程中列出应用程序域名并不容易,但可以done

但是,如果你想要一个dll&#39; s - native和.NET - 作为Tony the Lion答案的列表,那就是Process.Modules

答案 3 :(得分:1)

在 CLR v4 之后,接受的答案将仅显示非托管程序集。 如果要获取外部进程的托管程序集,可以参考: Microsoft.Diagnostics.Runtime

使用以下代码,您可以迭代外部进程的应用程序域并获取加载的程序集:

using var dt = DataTarget.AttachToProcess(clientProcess.Id, false);
assemblies = dt
      .ClrVersions
      .Select(dtClrVersion => dtClrVersion.CreateRuntime())
      .SelectMany(runtime => runtime.AppDomains.SelectMany(runtimeAppDomain => runtimeAppDomain.Modules))
      .Select(clrModule => clrModule.AssemblyName)
      .Distinct()
      .ToList();

有关详细信息,请参阅他们的 github