Page 1 of 1

WTSEnumProcesses() - Returns list of running processes

Posted: 24 Aug 2014, 20:46
by SKAN
WTSEnumProcesses( mode )
  • Mode 0 : List of PIDs ( comma delimited, a.k.a MatchList )
  • Mode 1 : List of PIDs along with Process name ( PID TAB PROCESS, Linefeed delimited )
  • Mode 2 : List of Processes ( Linefeed delimited )

    A_LastError will be total number of processes ( or -1 if function fails )
Hint: The list is chronologically ordered, that is, the newest process is at bottom.

Code: Select all

WTSEnumProcesses( Mode := 1 ) { ;        By SKAN,  http://goo.gl/6Zwnwu,  CD:24/Aug/2014 | MD:25/Aug/2014 
  Local tPtr := 0, pPtr := 0, nTTL := 0, LIST := ""

  If not DllCall( "Wtsapi32\WTSEnumerateProcesses", "Ptr",0, "Int",0, "Int",1, "PtrP",pPtr, "PtrP",nTTL )
    Return "", DllCall( "SetLastError", "Int",-1 )        
         
  tPtr := pPtr
  Loop % ( nTTL ) 
    LIST .= ( Mode < 2 ? NumGet( tPtr + 4, "UInt" ) : "" )           ; PID
         .  ( Mode = 1 ? A_Tab : "" )
         .  ( Mode > 0 ? StrGet( NumGet( tPtr + 8 ) ) "`n" : "," )   ; Process name  
  , tPtr += ( A_PtrSize = 4 ? 16 : 24 )                              ; sizeof( WTS_PROCESS_INFO )  
  
  StringTrimRight, LIST, LIST, 1
  DllCall( "Wtsapi32\WTSFreeMemory", "Ptr",pPtr )      

Return LIST, DllCall( "SetLastError", "UInt",nTTL ) 
}
WTSEnumProcesses() vs Example #4 provided in AHK Doc under Process command
  • Faster. ( Use DllCall( "LoadLibrary", "Str","Wtsapi32.dll" ) to prevent DLL from being unloaded )
  • Shorter, no debug privilege required.
  • Caller script does not require elevation.
MSDN links:
WTSEnumerateProcesses()
WTS_PROCESS_INFO structure
WTSFreeMemory()

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 25 Aug 2014, 02:55
by joedf
Wow great! I actually needed something like this... Thanks for sharing! :)

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 25 Aug 2014, 05:23
by guest3456
joedf wrote:Wow great! I actually needed something like this... Thanks for sharing! :)
lol, what did you need this for?

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 25 Aug 2014, 08:23
by joedf
I did some "test" projects... A so called memory cleaner, a "New process launch prevention" thingy, "task manager", bunch of Stuff :P

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 26 Aug 2014, 06:29
by lexikos
I wonder how it compares to WMI?

Code: Select all

WMIEnumProcesses() {
    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
        list .= process.ProcessID "`t" process.Name "`n"
    return list
}
I wrote most of that from memory; just had to look up the right name for "ProcessID". There is a lot more information available this way, and a bunch of other useful classes aside from Win32_Process.

There's a related example on the page for ComObjGet, but I think it was written before for-loops were implemented.

Edit: Ohhh, there's also an example on the page for the Process command, using for-loop. :lol:

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 26 Aug 2014, 09:19
by SKAN
lexikos wrote:I wonder how it compares to WMI?
It is like:

WTSAPI = 4ms
PSAPI = 5ms
WMI = 200ms
lexikos wrote:There is a lot more information available this way
Though not comparable to WMI, WTS_PROCESS_INFO_EX does provides decent amount of info.

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 26 Sep 2014, 05:54
by jNizM
just for info (something Bentschi did in 2011)

Code: Select all

msg := ""
for i, pid in EnumProcesses()
    msg .= pid ((pid=GetCurrentProcessId()) ? " [current]" : "") "`n"
MsgBox, % "Currently running Processes (PID):`n__________________`n`n" msg

msg := ""
for pid, name in EnumProcessNames()
    msg .= pid ": " name ((pid=GetCurrentProcessId()) ? " [current]" : "") "`n"
MsgBox, % "Currently running Processes (PID and Names):`n__________________`n`n" msg

pid := GetProcessId("firefox.exe")
MsgBox, % "Process ID of firefox.exe: " pid

EnumProcesses()
{
    static MaxProcesses := 1024
    VarSetCapacity(processarray, MaxProcesses*4, 0)
    if (!DllCall("EnumProcesses", "ptr", &processarray, "uint", MaxProcesses*4, "uint*", num))
        DllCall("psapi\EnumProcesses", "ptr", &processarray, "uint", MaxProcesses*4, "uint*", num)
    output := []
    loop % (num) ? num/4 : 0
        output.insert(NumGet(processarray, (A_Index-1)*4, "uint"))
    return output
}

EnumProcessImageNames()
{
    static MaxLength := 1024
    output := []
    for i, pid in EnumProcesses()
    {
        if (!(hProcess := DllCall("OpenProcess", "uint", 0x0400, "uint", 0, "uint", pid, "ptr")))
        {
            if (!(hProcess := DllCall("OpenProcess", "uint", 0x1000, "uint", 0, "uint", pid, "ptr")))
                continue
        }
        VarSetCapacity(name, MaxLength*2, 0)
        if (!(length := DllCall("GetProcessImageFileNameW", "ptr", hProcess, "ptr", &name, "uint", MaxLength)))
            length := DllCall("psapi\GetProcessImageFileNameW", "ptr", hProcess, "ptr", &name, "uint", MaxLength)
        if (length)
            output[pid] := StrGet(&name, MaxLength, "utf-16")
        DllCall("CloseHandle", "ptr", hProcess)
    }
    return output
}

EnumProcessNames()
{
    output := []
    for pid, name in EnumProcessImageNames()
        output[pid] := (p := instr(name, "\", 0, 0)) ? substr(name, p+1) : name
    return output
}

GetCurrentProcessId()
{
    return DllCall("GetCurrentProcessId", "uint")
}

GetProcessId(pid_or_name)
{
    output := GetProcessIds(pid_or_name)
    return output[output.minIndex()]
}

GetProcessIds(pid_or_name)
{
    output := []
    for i, pid in EnumProcesses()
    {
        if (pid=pid_or_name)
            output.insert(pid)
    }
    for pid, name in EnumProcessNames()
    {
        if (name=pid_or_name)
            output.insert(pid)
    }
    return output
}

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 27 Sep 2014, 21:11
by Skrell
Perhaps this is a stupid question (i'm not ahk pro) but how is this different/better than simply using WinGet, Id, List,,, Program Manager ?

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 27 Sep 2014, 21:28
by SKAN
Skrell wrote:how is this different/better than simply using WinGet, Id, List,,, Program Manager ?
Not all processes have windows and WinGet will list only with processes that has windows.

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 28 Sep 2014, 10:10
by Skrell
Ok then 2 thoughts:
1. Is your function faster than winget?
2. If yes, then is there a way to have your function only return with "windowed" processes ?

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 06 May 2015, 09:13
by Flipeador
Hello, someone could help me run this on a 64-bit system. I'm also trying to get the process name with this code, but I do not know how do this.

Code: Select all

dwSize := VarSetCapacity(lppe, 1032 + (A_PtrSize = 4 ? 32 : 48), 0), NumPut(dwSize, lppe)
hSnapshot := DLLCall("Kernel32.dll\CreateToolhelp32Snapshot", "UInt", 0x00000002, "UInt", 0)
	
DllCall("Kernel32.dll\Process32First", "Ptr", hSnapshot, "UInt", &lppe)
Loop {
	ProcessName := NumGet(lppe, 36, "Short") ; how get the process name (?
	ProcessId := NumGet(lppe, 24, "UInt")

	MsgBox % "ProcessName: " ProcessName
		. "`nProcessId: " ProcessId

	if !DllCall("Kernel32.dll\Process32Next", "Ptr", hSnapshot, "UInt", &lppe)
		break
}
	
DllCall("Kernel32.dll\CloseHandle", "Ptr", hSnapshot)
Thanks!

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 06 May 2015, 09:24
by jNizM
See this example (just press start):

Code: Select all

; GLOBAL SETTINGS ===============================================================================================================

#Warn
#NoEnv
#SingleInstance Force

; GUI ===========================================================================================================================

Gui, Margin, 5, 5
Gui, Add, Edit, xm ym w200 hWndhSearch vprcsearch
DllCall("user32.dll\SendMessage", "Ptr", hSearch, "UInt", 0x1501, "Ptr", 1, "Str", "Prozess Name here", "Ptr")
Gui, Add, Button, x+5 yp-1 w95 gSTART, % "Start"
Gui, Add, ListView, xm y+5 w300 h300, % "PID|Process Name"
LV_ModifyCol(1, 60), LV_ModifyCol(2, 210)
Gui, Add, Edit, xm y+5 w60 0x800 vprccount
Gui, Show, AutoSize
return

; SCRIPT ========================================================================================================================

START:
    Gui, Submit, NoHide
    WTSEnumProcesses(), LV_Delete()
    loop % arrLIST.MaxIndex()
    {
        i := A_Index
        if (InStr(arrLIST[i, "Process"], prcsearch))
            LV_Add("", arrLIST[i, "PID"], arrLIST[i, "Process"])
    }
    GuiControl,, prccount, % LV_GetCount()
return

; FUNCTIONS =====================================================================================================================

WTSEnumProcesses()
{
    local tPtr := pPtr := nTTL := 0, LIST := ""
    hModule := DllCall("kernel32.dll\LoadLibrary", "Str", "wtsapi32.dll", "Ptr")
    if !(DllCall("wtsapi32.dll\WTSEnumerateProcesses", "Ptr", 0, "UInt", 0, "UInt", 1, "Ptr*", pPtr, "UInt*", nTTL))
        return "", DllCall("kernel32.dll\SetLastError", "UInt", -1)

    tPtr := pPtr, arrLIST := []
    loop % (nTTL)
    {
        arrLIST[A_Index, "PID"]     := NumGet(tPtr + 4, "UInt")    ; ProcessId (PID)
        arrLIST[A_Index, "Process"] := StrGet(NumGet(tPtr + 8))    ; ProcessName
        tPtr += (A_PtrSize = 4 ? 16 : 24)                          ; sizeof(WTS_PROCESS_INFO)
    }

    DllCall("wtsapi32.dll\WTSFreeMemory", "Ptr", pPtr)

    if (hModule)
        DllCall("kernel32.dll\FreeLibrary", "Ptr", hModule)

    return arrLIST, DllCall("kernel32.dll\SetLastError", "UInt", nTTL)
}

; EXIT ==========================================================================================================================

GuiEscape:
GuiClose:
ExitApp

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 06 May 2015, 09:50
by Flipeador
Hi jNizM, thanks for your answer, but I want to use 'CreateToolhelp32Snapshot' because with that function can obtain the identifier of the process that created the process (its parent process) and the number of execution threads started by the process.
Is there any way to get that with 'WTSEnumerateProcesses'?

also wanted to know how to get the User SID with WTSEnumerateProcesses, then with LookupAccountSid get the user name and domain.

thanks

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 07 May 2015, 03:24
by jNizM
Something like this? (with WTSEnumerateProcessesEx)
Image

Code: Select all

; GLOBAL SETTINGS ===============================================================================================================

#Warn
#NoEnv
#SingleInstance Force

global WTS_EX := "SID|PID|Process Name|User SID|Name|Domain|Number of Threads|Handle Count|Pagefile Usage|Peak Pagefile Usage|Working Set Size|Peak Working Set Size|User Time|Kernel Time"

; GUI ===========================================================================================================================

Gui, Margin, 5, 5
Gui, Add, Edit, xm ym w200 hWndhSearch vprcsearch
DllCall("user32.dll\SendMessage", "Ptr", hSearch, "UInt", 0x1501, "Ptr", 1, "Str", "Prozess Name here", "Ptr")
Gui, Add, Button, x+5 yp-1 w95 gSTART, % "Start"
Gui, Add, ListView, xm y+5 w1200 h600, % WTS_EX
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50), LV_ModifyCol(3, 140), LV_ModifyCol(4, 60)
Gui, Add, Edit, xm y+5 w60 0x800 vprccount
Gui, Show, AutoSize
return

; SCRIPT ========================================================================================================================

START:
    Gui, Submit, NoHide
    WTSEnumerateProcessesEx(), LV_Delete()
    loop % WTS.MaxIndex()
    {
        if (InStr(WTS[A_Index, "PN"], prcsearch))
            LV_Add("", WTS[A_Index, "SID"]
                     , WTS[A_Index, "PID"]
                     , WTS[A_Index, "PN"]
                     , WTS[A_Index, "USID"]
                     , WTS[A_Index, "Name"]
                     , WTS[A_Index, "Domain"]
                     , WTS[A_Index, "NOT"]
                     , WTS[A_Index, "HC"]
                     , Num_Comma(Round(WTS[A_Index, "PU"] / 1024)) " K"
                     , Num_Comma(Round(WTS[A_Index, "PPU"] / 1024)) " K"
                     , Num_Comma(Round(WTS[A_Index, "WSS"] / 1024)) " K"
                     , Num_Comma(Round(WTS[A_Index, "PWSS"] / 1024)) " K"
                     , GetDurationFormat(WTS[A_Index, "UT"])
                     , GetDurationFormat(WTS[A_Index, "KT"]))
    }
    GuiControl,, prccount, % LV_GetCount()
return

; FUNCTIONS =====================================================================================================================

WTSEnumerateProcessesEx()
{
    local PI := pPI := nTTL := 0, LIST := use := ""
    hModule := DllCall("kernel32.dll\LoadLibrary", "Str", "wtsapi32.dll", "Ptr")
    if !(DllCall("wtsapi32.dll\WTSEnumerateProcessesEx", "Ptr", 0, "UInt*", 1, "UInt", 0xFFFFFFFE, "Ptr*", pPI, "UInt*", nTTL))
        return "", DllCall("kernel32.dll\SetLastError", "UInt", -1)

    PI := pPI, WTS := []
    loop % (nTTL)
    {
        WTS[A_Index, "SID"]     := NumGet(PI + 0, "UInt")      ; SessionId             ( The Remote Desktop Services session identifier for the session associated with the process. )
        WTS[A_Index, "PID"]     := NumGet(PI + 4, "UInt")      ; ProcessId             ( The process identifier that uniquely identifies the process on the RD Session Host server. )
        WTS[A_Index, "PN"]      := StrGet(NumGet(PI + 8))      ; pProcessName          ( A pointer to a null-terminated string that contains the name of the executable file associated with the process. )
        WTS[A_Index, "USID"]    := NumGet(PI + 16)             ; pUserSid              ( A pointer to the user security identifiers (SIDs) in the primary access token of the process. )
        VarSetCapacity(Name, 512, 0), VarSetCapacity(Domain, 512, 0)
        DllCall("advapi32.dll\LookupAccountSid", "Ptr", 0, "Ptr", NumGet(PI + 16), "Str", Name, "UIntP", 256, "Str", Domain, "UIntP", 256, "UIntP", use)
        WTS[A_Index, "Name"]    := Name
        WTS[A_Index, "Domain"]  := Domain
        WTS[A_Index, "NOT"]     := NumGet(PI + 24, "UInt")     ; NumberOfThreads       ( The number of threads in the process. )
        WTS[A_Index, "HC"]      := NumGet(PI + 28, "UInt")     ; HandleCount           ( The number of handles in the process. )
        WTS[A_Index, "PU"]      := NumGet(PI + 32, "UInt")     ; PagefileUsage         ( The page file usage of the process, in bytes. )
        WTS[A_Index, "PPU"]     := NumGet(PI + 36, "UInt")     ; PeakPagefileUsage     ( The peak page file usage of the process, in bytes. )
        WTS[A_Index, "WSS"]     := NumGet(PI + 40, "UInt")     ; WorkingSetSize        ( The working set size of the process, in bytes. )
        WTS[A_Index, "PWSS"]    := NumGet(PI + 44, "UInt")     ; PeakWorkingSetSize    ( The peak working set size of the process, in bytes. )
        WTS[A_Index, "UT"]      := NumGet(PI + 48, "Int64")    ; UserTime              ( The amount of time, in milliseconds, the process has been running in user mode. )
        WTS[A_Index, "KT"]      := NumGet(PI + 56, "Int64")    ; KernelTime            ( The amount of time, in milliseconds, the process has been running in kernel mode. )
        PI += 64
    }

    DllCall("wtsapi32.dll\WTSFreeMemoryEx", "Ptr", 1, "Ptr", pPI, "UInt", nTTL)

    if (hModule)
        DllCall("kernel32.dll\FreeLibrary", "Ptr", hModule)

    return WTS, DllCall("kernel32.dll\SetLastError", "UInt", nTTL)
}

GetDurationFormat(VarIn, Format := "hh:mm:ss.fff")
{
    VarSetCapacity(VarOut, 128, 0), VarIn := VarIn
    if !(DllCall("kernel32.dll\GetDurationFormat", "UInt", 0x400, "UInt", 0, "Ptr", 0, "Int64", VarIn, "WStr", Format, "WStr", VarOut, "Int", 2048))
        return DllCall("kernel32.dll\GetLastError")
    return VarOut
}

Num_Comma(num)
{
    n := DllCall("kernel32.dll\GetNumberFormat", "UInt", 0x0400, "UInt", 0, "Str", num, "Ptr", 0, "Ptr", 0, "Int", 0)
    VarSetCapacity(s, n * (A_IsUnicode ? 2 : 1), 0)
    DllCall("kernel32.dll\GetNumberFormat", "UInt", 0x0400, "UInt", 0, "Str", num, "Ptr", 0, "Str", s, "Int", n)
    return SubStr(s, 1, StrLen(s) - 3)
}

; EXIT ==========================================================================================================================

GuiEscape:
GuiClose:
ExitApp

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 07 May 2015, 14:39
by Iomega0318
Interesting, also great job :)

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 04 Sep 2015, 08:38
by serg
jNizM, thanks for sharing this code!

Is there a way to get CPU usage for each process? (I saw function GetProcessTimes() here on forum, but couldnt figure out how to make it work)

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 05 Sep 2015, 17:38
by Guest10
This gives you more info. Not sure what Wording Set, Peak Working Set, etc. are. :morebeard:

Code: Select all

; http://www.autohotkey.com/board/topic/38653-see-running-autohotkey-scripts-and-end-them/

#SingleInstance Force
#NoEnv

DetectHiddenWindows, On

Gui, +Resize -MaximizeBox
Gui, Add, ListView, w510 h250 vlvwList hwndhlvwList gListClick, PID|Script Path|Working Set|Peak Working Set|Page File|Peak Page File
Gui, Add, Button, y+10 xp w250 hwndhRefresh gRefresh, Refresh list
Gui, Add, Button, yp x+10 wp hwndhEndProc gEndProc, End associated process
Gui, Show, x50 y250

Gui, Show
Sleep 250 ; Give time for Anchor to catch on
RefreshList()
Return

GuiClose:
ExitApp

GuiSize:
    Anchor(hlvwList, "wh")
    Anchor(hRefresh, "y w0.5")
    Anchor(hEndProc, "x0.5 y w0.5")
Return

Refresh:
    RefreshList()
Return

ListClick:
    If (A_GuiEvent <> "DoubleClick")
        Return
EndProc:
    
    i := LV_GetNext()
    WinKill, % "ahk_id " AHKWindows%i%
    RefreshList()
    
Return

RefreshList() {
    Global
    
    LV_Delete()
    WinGet, AHKWindows, List, ahk_class AutoHotkey
    
    Loop %AHKWindows% {
        
        ;Get process ID
        WinGet, AHKWindows%A_Index%_PID, PID, % "ahk_id " AHKWindows%A_Index%
        GetProcessMemoryInfo(AHKWindows%A_Index%_PID)
        
        ;Get memory info
        LV_Add(0, AHKWindows%A_Index%_PID, GetScriptPathFromHwnd(AHKWindows%A_Index%)
        , Round(GetProcessMemoryInfo(0,12) / 1024) " K", Round(GetProcessMemoryInfo(0,8) / 1024) " K"
        , Round(GetProcessMemoryInfo(0,32) / 1024) " K", Round(GetProcessMemoryInfo(0,36) / 1024) " K")
    }
    
    Loop 6
        LV_ModifyCol(A_Index, "AutoHdr")
    
    ;Get columns width
    iColWidth := 0
    Loop 6 {
        SendMessage, 4125, A_Index - 1, 0,, ahk_id %hlvwList%
        iColWidth += ErrorLevel
    }
    
    ;Set main width in accordance to column width
    iWidth := iColWidth + 24
    Gui, Show, w%iWidth%
}

GetScriptPathFromHwnd(hwnd) {
    WinGetTitle, win, ahk_id %hwnd%
    Return RegExMatch(win, ".*(?= - AutoHotkey v[0-9\.]+)", ret) ? ret : win
}

GetProcessMemoryInfo(pid, info=-1) {
    Static uMemCounters := 0
    
    ;Check if we just want info from the struct
    If (info <> -1)
        Return NumGet(uMemCounters, info)
    Else {
        
        ;Open the process with PROCESS_QUERY_INFORMATION and PROCESS_VM_READ
        h := DllCall("OpenProcess", "UInt", 0x0410, "UInt", 0, "UInt", pid)
        
        ;Put info into struct
        If Not uMemCounters ;Check if it hasn't already been initialized
            VarSetCapacity(uMemCounters, 40)
        DllCall("Psapi.dll\GetProcessMemoryInfo", "UInt", h, "UInt", &uMemCounters, "UInt", 40)
        
        ;Done
        DllCall("CloseHandle", "UInt", h)
    }
}

;Anchor() by Titan
;http://www.autohotkey.com/forum/viewtopic.php?t=4348
Anchor(i, a = "", r = false) {
    static c, cs = 12, cx = 255, cl = 0, g, gs = 8, z = 0, k = 0xffff, gx = 1
    If z = 0
        VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), z := true
    If a =
    {
        StringLeft, gn, i, 2
        If gn contains :
        {
            StringTrimRight, gn, gn, 1
            t = 2
        }
        StringTrimLeft, i, i, t ? t : 3
        If gn is not digit
            gn := gx
    }
    Else gn := A_Gui
    If i is not xdigit
    {
        GuiControlGet, t, Hwnd, %i%
        If ErrorLevel = 0
            i := t
        Else ControlGet, i, Hwnd, , %i%
    }
    gb := (gn - 1) * gs
    Loop, %cx%
        If (NumGet(c, cb := cs * (A_Index - 1)) == i) {
            If a =
            {
                cf = 1
                Break
            }
            Else gx := A_Gui
            d := NumGet(g, gb), gw := A_GuiWidth - (d >> 16 & k), gh := A_GuiHeight - (d & k), as := 1
                , dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
                , dw := NumGet(c, cb + 8, "Short"), dh := NumGet(c, cb + 10, "Short")
            Loop, Parse, a, xywh
                If A_Index > 1
                    av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
                        , d%av% += (InStr("yh", av) ? gh : gw) * (A_LoopField + 0 ? A_LoopField : 1)
            DllCall("SetWindowPos", "UInt", i, "Int", 0, "Int", dx, "Int", dy, "Int", dw, "Int", dh, "Int", 4)
            If r != 0
                DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
            Return
        }
    If cf != 1
        cb := cl, cl += cs
    If (!NumGet(g, gb)) {
        Gui, %gn%:+LastFound
        WinGetPos, , , , gh
        VarSetCapacity(pwi, 68, 0), DllCall("GetWindowInfo", "UInt", WinExist(), "UInt", &pwi)
            , NumPut(((bx := NumGet(pwi, 48)) << 16 | by := gh - A_GuiHeight - NumGet(pwi, 52)), g, gb + 4)
            , NumPut(A_GuiWidth << 16 | A_GuiHeight, g, gb)
    }
    Else d := NumGet(g, gb + 4), bx := d >> 16, by := d & k
    ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
    If cf = 1
    {
        Gui, %gn%:+LastFound
        WinGetPos, , , gw, gh
        d := NumGet(g, gb), dw -= gw - bx * 2 - (d >> 16), dh -= gh - by - bx - (d & k)
    }
    NumPut(i, c, cb), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
        , NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
    Return, true
}

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 29 Oct 2022, 02:51
by lmstearn
Thanks for posting! This one returns an associative array based on name.

Code: Select all

list := ""
	for name, pid in WTSEnumProcesses()
	list .= name . "`, " . pid . " |"
msgbox %list%
WTSEnumProcesses()
{
; By SKAN,  http://goo.gl/6Zwnwu,  CD:24/Aug/2014 | MD:25/Aug/2014 
tPtr := 0, pPtr := 0, nTTL := 0, list := [], name := "", piOffset := (A_PtrSize==4?16:24)

	if not DllCall("Wtsapi32\WTSEnumerateProcesses", "Ptr", 0, "Int", 0, "Int", 1, "PtrP", pPtr, "PtrP", nTTL)
	{
	DllCall("SetLastError", "Int", -1)
	return list
	}

tPtr := pPtr
	loop %nTTL%
	{
	name := StrGet(NumGet(tPtr + 8 ))
	list[name] := NumGet(tPtr + 4, "UInt")
	tPtr += piOffset ; sizeof( WTS_PROCESS_INFO ) 
	}

DllCall("Wtsapi32\WTSFreeMemory", "Ptr", pPtr) ; No return value
DllCall("SetLastError", "UInt", nTTL)
Return list
}

Re: WTSEnumProcesses() - Returns list of running processes

Posted: 16 May 2024, 02:20
by neogna2
v2 version by just me