版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
在教程 vb.net 教程 6-3 进程加载的模块 中详细讲解了使用 Process类的modules属性,该属性可以获取进程加载的所有Dll文件,详细使用可以参看上述博文。
但是在实际使用中存在一个问题:对于有些程序,不能获得其进程全部的加载模块。
例如,获得QQExternal的加载模块,如果使用.Net只能获得5个dll。但是通过其它工具,可以看到实际包含了很多dll:
通过调用系统api可以很好地解决这个问题。
调用的api声明如下:
打开进程,以便执行后续操作:
Declare Function OpenProcess Lib "kernel32" Alias "OpenProcess" (
ByVal dwDesiredAccess As Integer,
ByVal bInheritHandle As Integer,
ByVal dwProcessId As Integer
) As IntPtr
枚举进程模块:
Declare Function EnumProcessModulesEx Lib "PSAPI.DLL" (
ByVal hProcess As IntPtr,
ByVal lphModule() As Long,
ByVal cb As Integer,
ByRef cbNeeded As Integer,
ByVal dwFilterFlag As Integer
) As Integer
获得模块文件路径:
Declare Function GetModuleFileNameEx Lib "PSAPI.DLL" Alias "GetModuleFileNameExA" (
ByVal hProcess As IntPtr,
ByVal hModule As IntPtr,
ByVal lpFileName As System.Text.StringBuilder,
ByVal nSize As Integer) As Integer
关闭句柄:
Declare Function CloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As Integer) As Integer
根据以上API函数,获得模块的代码如下:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.LoadFor Each pro As Process In Process.GetProcessesDim lvPro As New ListViewItem(pro.ProcessName)lvPro.SubItems.Add(pro.Id)Me.ListView1.Items.Add(lvPro)NextEnd SubPrivate Sub ListView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListView1.SelectedIndexChangedIf ListView1.SelectedItems.Count <> 1 ThenExit SubEnd IfDim lvpro As New ListViewItem()lvpro = ListView1.SelectedItems(0)Dim proid As Integer = Integer.Parse(lvpro.SubItems(1).Text)Dim prohandle As Integer = Integer.Parse(lvpro.SubItems(1).Text)Call listModNet(proid)Call listModApi(proid)End SubPrivate Sub listModNet(ByVal proid As Integer)Dim pro As Process = Process.GetProcessById(proid)Dim lvMod As ListViewItemListView2.Items.Clear()TryTextBox2.Text = pro.Modules.CountFor Each proMod As ProcessModule In pro.ModuleslvMod = New ListViewItem(proMod.ModuleName)lvMod.SubItems.Add(proMod.BaseAddress.ToInt64)lvMod.SubItems.Add(proMod.FileVersionInfo.FileVersion)lvMod.SubItems.Add(proMod.ModuleMemorySize)lvMod.SubItems.Add(proMod.FileName)ListView2.Items.Add(lvMod)NextCatch ex As ExceptionTextBox2.Text = "err:" & ex.MessageEnd TryEnd SubPublic Const PROCESS_QUERY_INFORMATION = 1024Public Const PROCESS_VM_READ = 16Const LIST_MODULES_ALL = 3Declare Function OpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Integer,ByVal bInheritHandle As Integer,ByVal dwProcessId As Integer) As IntPtrDeclare Function EnumProcessModulesEx Lib "PSAPI.DLL" (ByVal hProcess As IntPtr,ByRef lphModule As IntPtr,ByVal cb As Integer,ByRef cbNeeded As Integer,ByVal dwFilterFlag As Integer) As IntegerDeclare Function EnumProcessModulesEx Lib "PSAPI.DLL" (ByVal hProcess As IntPtr,ByVal lphModule() As Long,ByVal cb As Integer,ByRef cbNeeded As Integer,ByVal dwFilterFlag As Integer) As IntegerDeclare Function GetModuleFileNameEx Lib "PSAPI.DLL" Alias "GetModuleFileNameExA" (ByVal hProcess As IntPtr,ByVal hModule As IntPtr,ByVal lpFileName As System.Text.StringBuilder,ByVal nSize As Integer) As IntegerDeclare Function CloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As Integer) As IntegerPrivate Sub listModApi(ByVal proid As Integer)ListBox1.Items.Clear()Dim prohandle As IntPtrprohandle = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, proid)Dim maxMod As Integer = 1024Dim pmod() As LongReDim pmod(0)Dim cb As Integercb = System.Runtime.InteropServices.Marshal.SizeOf(pmod(0))Dim cbneeded As IntegerDim result As Integerresult = EnumProcessModulesEx(prohandle, pmod, 8, cbneeded, LIST_MODULES_ALL)cb = cbneeded / 8ReDim pmod(cb - 1)result = EnumProcessModulesEx(prohandle, pmod, cb * 8, cbneeded, LIST_MODULES_ALL)If result = 0 ThenTextBox1.Text = "err:" & Err.LastDllErrorElseTextBox1.Text = cbneeded / 8For i As Integer = 0 To pmod.Count - 1Dim modfilename As New System.Text.StringBuilder(255)result = GetModuleFileNameEx(prohandle, pmod(i), modfilename, 255)ListBox1.Items.Add(modfilename)NextEnd IfCloseHandle(prohandle)End Sub
对于部分进程,需要使用管理员权限才能打开查看。
运行时如下:
可以看到.Net中获得5个模块,但是通过API可以发现,QQExternal的进程下有105个模块,相差比较大。但是原因尚不明确。
关于API的调用,请参看以下博文:
第27章 API的调用
由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。
学习更多vb.net知识,请参看vb.net 教程 目录