c# - 如何在 C# 中获取所有进程模块?
问题描述
我知道 System.Diagnostics 中有一个 process.Modules 列表,其中包含一些流程模块,但我遇到了一些麻烦,因为我在这里找不到一些 dll:
Process process = Memory.GetProcessByName("csgo");
foreach (ProcessModule pm in process.Modules)
Console.WriteLine(pm.ModuleName);
所以我一直在寻找一个解决方案来让它工作,我在 pinvoke.net 中发现了一些有趣的东西,但它也没有工作:
var snapshot = CreateToolhelp32Snapshot(SnapshotFlags.Module, (uint)process.Id);
MODULEENTRY32 mod = new MODULEENTRY32() {
dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32))
};
if (!Module32First((IntPtr)snapshot, ref mod))
return;
do { Console.WriteLine(mod.szModule); } while (Module32Next((IntPtr)snapshot, ref mod));
然后我在C++中搜索了相同代码的实现,它工作了
#include <windows.h>
#include <iostream>
#include <TlHelp32.h>
#include <string>
#include <sstream>
using namespace std;
int main() {
int a;
cin >> a;
HANDLE snapshot = CreateToolhelp32Snapshot(0x00000008, a);
MODULEENTRY32 mod;
mod.dwSize = sizeof(mod);
if (!Module32First(snapshot, &mod))
return 0;
do { cout << mod.szModule << endl; } while (Module32Next(snapshot, &mod));
system("pause");
return 0;
}
所以我的问题是:第二个和第三个变体有什么区别,我怎样才能让它在 C# 中工作?我还尝试使用来自 user32.dll 的 OpenProcess() 和来自 kernel32.dll 的 GetModuleHandle() 但它不起作用。
解决方案
您必须将代码编译为 x64 并以管理员身份运行才能获取所有模块。
或者将其用作您的快照类型:
TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32
这是 C# 中 CreateToolHelp32Snapshot() 模块循环的样子:
const Int64 INVALID_HANDLE_VALUE = -1;
[Flags]
private enum SnapshotFlags : uint
{
HeapList = 0x00000001,
Process = 0x00000002,
Thread = 0x00000004,
Module = 0x00000008,
Module32 = 0x00000010,
Inherit = 0x80000000,
All = 0x0000001F,
NoHeaps = 0x40000000
}
[StructLayout(LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public struct MODULEENTRY32
{
internal uint dwSize;
internal uint th32ModuleID;
internal uint th32ProcessID;
internal uint GlblcntUsage;
internal uint ProccntUsage;
internal IntPtr modBaseAddr;
internal uint modBaseSize;
internal IntPtr hModule;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
internal string szModule;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
internal string szExePath;
}
[DllImport("kernel32.dll")]
static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme);
[DllImport("kernel32.dll")]
static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme);
[DllImport("kernel32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle([In] IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, IntPtr th32ProcessID);
public static IntPtr GetModuleBaseAddress(IntPtr procId, string modName)
{
IntPtr modBaseAddr = IntPtr.Zero;
IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Module | SnapshotFlags.Module32, procId);
if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry = new MODULEENTRY32();
modEntry.dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32));
if (Module32First(hSnap, ref modEntry))
{
do
{
if (modEntry.szModule.Equals(modName))
{
modBaseAddr = modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, ref modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
推荐阅读
- python - 使用 Anaconda installe 在 Windows 上获取 CUDA 和 CUDNN 版本
- docker - 如何在本地机器上使用带有 sdk 的云构建来构建 docker 映像而不会死去尝试
- winforms - 如何在 Winforms 应用程序中使用 Windows Login 访问 SAML Service Provider
- java - 在 if 语句中比较 Doubles 的问题
- python-3.x - 使用 xlrd 读取 .xlsx 文件的格式信息
- python-3.x - 如何在scrapy中刮取具有特定标题的跨度?
- c++ - 为什么在 hdc 上绘图不立即更新窗口?
- ignite - 将缓存加载到 apache ignite 失败并出现异常
- twilio - Twilio 无效的访问令牌签名 (iOS - Swift)
- database - 具有多种类型的 AWS DynamoDB 索引属性