如何检测进程是否被挂起
本帖最后由 朱雅琼 于 2010-8-27 13:39 编辑RT...请大大指教? 不懂帮顶。希望有人能帮你解决。 我怎么看不懂啊。哪个来解释一下LZ说的什么。 http://www.autoitx.com/forum.php?mod=viewthread&tid=7374&highlight=%BD%F8%B3%CC%B9%D2%C6%F0
看这个帖,如果进程被这个函数挂起,如何检测出来..进程已经被挂起,也就是已经被暂停..!~ “如果”已经改成“如何”了啊,因为你的错字,即便第一天就看见你的帖子,但还是不会回复你。
既然已经改过来了,那就告诉你:
挂起一个进程,实际是挂起了这个进程的主线程。
NtQuerySystemInformation(ntdll.dll)的5号功能可以枚举系统中所有的进程和线程,调用这个函数之后,会取得一个SYSTEM_PROCESS_INFORMATION结构,这个结构的长度是不定的。
SYSTEM_PROCESS_INFORMATION结构:ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2;
ULONG PrivatePageCount;
VM_COUNTERS VirtualMemoryCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD Threads;这个结构实际是个单向链表,第一个成员NextEntryOffset表示下一个进程信息的偏移,从NextEntryOffset开始到IoCounters,这段结构的长度是确定的(184字节),记录着进程的多种信息,比如ImageName表示进程的映像名称,ProcessId表示进程的PID,InheritedFromProcessId是父进程的ID,CreateTime是进程的创建时间等等。
Threads是进程的线程信息,实际是个数组,数组的元素数量是不确定的,因为每个进程的线程数量都是不确定的,SYSTEM_THREAD的结构:LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
LONG BasePriority;
ULONG ContextSwitchCount;
ULONG State;
KWAIT_REASON WaitReason;
这一段记录着线程的各种信息,StartAddress是线程的起始地址,ClientId是进程ID与线程ID,Priority线程优先级。其中的State和WaitReason分别表示线程的状态和等待原因,只要读取这两个信息就能判断出进程是否处于挂起状态,当两个的值都为5时,表示线程正处于挂起状态。
紧跟IoCounters其后的第一个SYSTEM_THREAD表示进程的第一个线程(即主线程),然后接着第一个SYSTEM_THREAD之后还是一个SYSTEM_THREAD,表示进程的第2个线程,依此。在其后到底要紧跟几个SYSTEM_THREAD,取决于SYSTEM_PROCESS_INFORMATION的第2个成员NumberOfThreads(线程数量)。
1、调用NtQuerySystemInformation的5号功能获取系统中的所有进程,取得SYSTEM_PROCESS_INFORMATION结构指针。
2、通过指针枚举所有进程,判断ProcessId是否是目标进程,不是则当前指针加NextEntryoffset,使指针指向下一进程信息,继续枚举。如是,读取第一个SYSTEM_THREAD(主线程)中的State和WaitReason,如果值都是5,说明进程处于挂起状态。
3、判断NextEntryOffset是否为0,为0则停止枚举。
以上。
PS:如果你想做伸手党,肯定会被无视。当然,如果事先自己独立思考过 又是另外一回事。 那个功能太强了。配合做杀毒软件 大大..这么深奥的东西..我真的写不出来的.. 简单点可以用API SendMessageTimeout, 如果消息响应超时,说明进程挂起了 学习啊,太厉害了,,看都看不懂,何况要写了? 呵呵,学习一下。。 好吧,我承认我5#的回复实在是多余了,楼主觉得呢?
#include <Thread.au3>
$iProcessId = ProcessExists("Notepad.exe")
If ($iProcessId = 0) Then Exit
$aThread = _RTEnumerateThreads($iProcessId)
If ($aThread = 5) And ($aThread = 5) Then
MsgBox(48, "", "Process " & $iProcessId & " is suspended.")
Else
MsgBox(48, "", "Process " & $iProcessId & " is not suspended.")
EndIf
_RTEnumerateThreads 原型:
Func _RTEnumerateThreads($iProcessId = 0)
Local $pBuffer, $iOffset, $pThreads, $pBuffer1, $aResult = []
If (@NumParams) Then
If $iProcessId = -1 Then $iProcessId = @AutoItPid
$iProcessId = ProcessExists($iProcessId)
If Not $iProcessId Then Return SetError(2, 0, $aResult)
EndIf
_RTQuerySystemInformation(5, 0, 0)
If (@Extended = 0) Then Return SetError(@error, 0, $aResult)
$pBuffer = _RTHeapAlloc(@Extended)
If _RTQuerySystemInformation(5, $pBuffer, @Extended) = False Then
Return SetError(@error, _RTHeapFree($pBuffer), $aResult)
EndIf
$pBuffer1 = $pBuffer
If @NumParams Then
While 1
$iOffset = _RTReadBytes($pBuffer)
If _RTReadBytes($pBuffer + 68) <> $iProcessId Then
If ($iOffset) Then
$pBuffer += $iOffset
ContinueLoop
Else
ExitLoop
EndIf
EndIf
$aResult = _RTReadBytes($pBuffer + 4)
$pThreads = $pBuffer + 184
Redim $aResult[$aResult + 1]
For $i = 1 To $aResult
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 36); ThreadId
$aResult[$i] = $iProcessId ; ProcessId
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 40); Priority
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 44); BPriority
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 28, "ptr")
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 48); CSwitch
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 52); State
$aResult[$i] = _RTReadBytes($pThreads + ($i - 1) * 64 + 56); Reason
Next
ExitLoop
WEnd
Else
Local $iPrevIndex = 1
While 1
$iOffset = _RTReadBytes($pBuffer)
$aResult += _RTReadBytes($pBuffer + 4)
$pThreads = $pBuffer + 184
Redim $aResult[$aResult + 1]
For $i = $iPrevIndex To $aResult
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 36)
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 32)
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 40)
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 44)
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 28, "ptr")
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 48)
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 52)
$aResult[$i] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 56)
Next
If ($iOffset = 0) Then ExitLoop
$pBuffer += $iOffset
$iPrevIndex = $aResult + 1
WEnd
EndIf
Return SetError(0, _RTHeapFree($pBuffer1), $aResult)
EndFunc ;==>_RTEnumerateThreads 回复 11# pusofalse
没有5楼的说明就更加看不懂11楼的原理了
NtQuerySystemInformation(ntdll.dll)的5号功能就这么强大,也勉强看明白了
能不能再像5楼那样介绍下其它的功能呢
页:
[1]