【问题标题】:Monitor spawned processes (process tree) from AHK从 AHK 监控生成的进程(进程树)
【发布时间】:2019-12-11 01:19:11
【问题描述】:

我一直在搜索(搜索引擎、SO、AHK 论坛)如何获取由Run[Wait] 命令运行的任何东西的层次结构树的 PID,但没有成功。

任何帮助/指导将不胜感激。

【问题讨论】:

  • 可以通过win apiWin32_Process,AHK例子here查询进程详情。您可以通过递归读取ParentProcessId来构建任何根进程的进程树。
  • 谢谢,我做到了,速度太慢了,我简直不敢相信。我将等待另一个答案,同时我有一个工作得更好的 DLL 调用。如果没有任何结果,将作为答案发布。
  • 马上开始:您可能会多次调用Select * ...,这可能是性能不佳的原因。尝试一次选择所有进程并处理内存中的数据。再说一次,你为什么不在这里发布你的代码,以便我们一起改进它呢?
  • 不,我只选择了 ProcessId,ParentProcessId WHERE ParentProcessId = pid。 OTOH,选择所有 PID 并为每个孩子进行迭代会更好。愚蠢的我,这样的疏忽。非常感谢先生。

标签: process tree autohotkey pid


【解决方案1】:

在寻找 30 个子进程树的 20 次迭代中,我的平均时间是:

  • DLL:0.2587435
  • WMI:0.1113015

这是板凳:

pid := 7880
loops := 20

time_dll := 0
Loop, % loops
{
    QPC(1)
    tree_dll := processTree(pid)
    time_dll += QPC()
}
time_dll /= loops

time_wmi := 0
Loop, % loops
{
    QPC(1)
    tree_wmi := processTree(pid, True)
    time_wmi += QPC()
}
time_wmi /= loops

MsgBox,,>, % "DLL: " time_dll "`nWMI: " time_wmi

;-------------------------------------------------------------------------------

processTree(pid, wmi := False, obj := False)
{
    Local
    tree := []
    If wmi
    {
        If !obj
            obj := ComObjGet("winmgmts:").ExecQuery("SELECT ProcessId,ParentProcessId FROM Win32_Process")
        tree := []
        For result in obj
            If pid = result.ParentProcessId
            {
                tree.Push(result.ProcessId)
                subs := %A_ThisFunc%(result.ProcessId, True, obj)
                For idx,val in subs
                    tree.Push(val)
            }
    }
    Else
    {
        Static MAX_PATH := 260 << !!A_IsUnicode
        Static varCapacity := MAX_PATH
        VarSetCapacity(lppe, varCapacity)
        NumPut(varCapacity, lppe, "UInt")
        hSnapshot := DllCall("CreateToolhelp32Snapshot", "UInt",0x2, "UInt",pid, "Ptr")
        DllCall("Process32First", "Ptr",hSnapshot, "Ptr",&lppe)
        Loop
        {
            parent := NumGet(lppe, 16 + A_PtrSize * 2, "UInt")
            If (parent = pid)
            {
                child := NumGet(lppe, 8, "UInt")
                tree.Push(child)
                gchilds := %A_ThisFunc%(child)
                For idx,val in gchilds
                    tree.Push(val)
            }
        } Until !DllCall("Process32Next", "Ptr",hSnapshot, "Ptr",&lppe)
        DllCall("CloseHandle", "Ptr",hSnapshot)
    }
    Return, tree
}

QPC(start := 0)
{
    Static P := 0, F := 0, Q := DllCall("QueryPerformanceFrequency", "Int64P",F)
    Return !DllCall("QueryPerformanceCounter", "Int64P",Q) + (start ? (P:=Q)/F : (Q-P)/F)
}

【讨论】:

  • 不错的一个。您可能会从按父 PID 排序和进行二分搜索中得到提升。这应该会大大减少查找次数。或者同样有希望且更容易实现:构建您自己的对象/字典并按父 PID 对所有进程进行分组。
  • 我喜欢这个想法,但那将是矫枉过正......这将是用户交互的一部分,所以十分之一秒似乎是一个公平的交易。非常感谢您的帮助和见解。
猜你喜欢
  • 2023-03-24
  • 2011-09-14
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多