找回密码
 加入
搜索
查看: 3789|回复: 11

[系统综合] 如何检测进程是否被挂起

 火.. [复制链接]
发表于 2010-8-27 11:07:18 | 显示全部楼层 |阅读模式
本帖最后由 朱雅琼 于 2010-8-27 13:39 编辑

RT...请大大指教?
发表于 2010-8-28 17:02:17 | 显示全部楼层
不懂帮顶。希望有人能帮你解决。
发表于 2010-8-28 17:49:29 | 显示全部楼层
我怎么看不懂啊。哪个来解释一下LZ说的什么。
 楼主| 发表于 2010-8-28 22:27:30 | 显示全部楼层
http://www.autoitx.com/forum.php ... 8%B3%CC%B9%D2%C6%F0

看这个帖,如果进程被这个函数挂起,如何检测出来..进程已经被挂起,也就是已经被暂停..!~
发表于 2010-8-29 14:34:56 | 显示全部楼层
“如果”已经改成“如何”了啊,因为你的错字,即便第一天就看见你的帖子,但还是不会回复你。
既然已经改过来了,那就告诉你:

挂起一个进程,实际是挂起了这个进程的主线程。

NtQuerySystemInformation(ntdll.dll)的5号功能可以枚举系统中所有的进程和线程,调用这个函数之后,会取得一个SYSTEM_PROCESS_INFORMATION结构,这个结构的长度是不定的。

SYSTEM_PROCESS_INFORMATION结构:
  ULONG                   NextEntryOffset;
  ULONG                   NumberOfThreads;
  LARGE_INTEGER           Reserved[3];
  LARGE_INTEGER           CreateTime;
  LARGE_INTEGER           UserTime;
  LARGE_INTEGER           KernelTime;
  UNICODE_STRING          ImageName;
  KPRIORITY               BasePriority;
  HANDLE                  ProcessId;
  HANDLE                  InheritedFromProcessId;
  ULONG                   HandleCount;
  ULONG                   Reserved2[2];
  ULONG                   PrivatePageCount;
  VM_COUNTERS             VirtualMemoryCounters;
  IO_COUNTERS             IoCounters;
  SYSTEM_THREAD           Threads[0];
这个结构实际是个单向链表,第一个成员NextEntryOffset表示下一个进程信息的偏移,从NextEntryOffset开始到IoCounters,这段结构的长度是确定的(184字节),记录着进程的多种信息,比如ImageName表示进程的映像名称,ProcessId表示进程的PID,InheritedFromProcessId是父进程的ID,CreateTime是进程的创建时间等等。
Threads[0]是进程的线程信息,实际是个数组,数组的元素数量是不确定的,因为每个进程的线程数量都是不确定的,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:如果你想做伸手党,肯定会被无视。当然,如果事先自己独立思考过 又是另外一回事。

评分

参与人数 1贡献 +5 收起 理由
afan + 5

查看全部评分

发表于 2010-8-29 19:03:52 | 显示全部楼层
那个功能太强了。配合做杀毒软件
 楼主| 发表于 2010-8-29 23:14:40 | 显示全部楼层
大大..这么深奥的东西..我真的写不出来的..
发表于 2010-8-30 08:32:29 | 显示全部楼层
简单点可以用API SendMessageTimeout, 如果消息响应超时,说明进程挂起了
发表于 2010-9-16 22:44:35 | 显示全部楼层
学习啊,太厉害了,,看都看不懂,何况要写了?
发表于 2010-9-18 14:12:57 | 显示全部楼层
呵呵,学习一下。。
发表于 2010-9-18 22:29:17 | 显示全部楼层
好吧,我承认我5#的回复实在是多余了,楼主觉得呢?

#include <Thread.au3>

$iProcessId = ProcessExists("Notepad.exe")
If ($iProcessId = 0) Then Exit

$aThread = _RTEnumerateThreads($iProcessId)
If ($aThread[1][6] = 5) And ($aThread[1][7] = 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[1][8] = [[0]]

        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[0][0] = _RTReadBytes($pBuffer + 4)
                        $pThreads = $pBuffer + 184

                        Redim $aResult[$aResult[0][0] + 1][8]

                        For $i = 1 To $aResult[0][0]
                                $aResult[$i][0] = _RTReadBytes($pThreads + ($i - 1) * 64 + 36); ThreadId
                                $aResult[$i][1] = $iProcessId        ; ProcessId
                                $aResult[$i][2] = _RTReadBytes($pThreads + ($i - 1) * 64 + 40); Priority
                                $aResult[$i][3] = _RTReadBytes($pThreads + ($i - 1) * 64 + 44); BPriority
                                $aResult[$i][4] = _RTReadBytes($pThreads + ($i - 1) * 64 + 28, "ptr")
                                $aResult[$i][5] = _RTReadBytes($pThreads + ($i - 1) * 64 + 48); CSwitch
                                $aResult[$i][6] = _RTReadBytes($pThreads + ($i - 1) * 64 + 52); State
                                $aResult[$i][7] = _RTReadBytes($pThreads + ($i - 1) * 64 + 56); Reason
                        Next
                        ExitLoop
                WEnd
        Else
                Local $iPrevIndex = 1
                While 1
                        $iOffset = _RTReadBytes($pBuffer)

                        $aResult[0][0] += _RTReadBytes($pBuffer + 4)
                        $pThreads = $pBuffer + 184

                        Redim $aResult[$aResult[0][0] + 1][8]

                        For $i = $iPrevIndex To $aResult[0][0]
                                $aResult[$i][0] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 36)
                                $aResult[$i][1] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 32)
                                $aResult[$i][2] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 40)
                                $aResult[$i][3] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 44)
                                $aResult[$i][4] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 28, "ptr")
                                $aResult[$i][5] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 48)
                                $aResult[$i][6] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 52)
                                $aResult[$i][7] = _RTReadBytes($pThreads + ($i - $iPrevIndex) * 64 + 56)
                        Next
                        If ($iOffset = 0) Then ExitLoop

                        $pBuffer += $iOffset
                        $iPrevIndex = $aResult[0][0] + 1
                WEnd

        EndIf
        Return SetError(0, _RTHeapFree($pBuffer1), $aResult)
EndFunc        ;==>_RTEnumerateThreads
发表于 2010-9-19 01:30:19 | 显示全部楼层
回复 11# pusofalse


    没有5楼的说明就更加看不懂11楼的原理了
NtQuerySystemInformation(ntdll.dll)的5号功能就这么强大,也勉强看明白了
能不能再像5楼那样介绍下其它的功能呢
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-20 06:52 , Processed in 0.088776 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表