WTSEnumProcesses() - Returns list of running processes

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

WTSEnumProcesses() - Returns list of running processes

24 Aug 2014, 20:46

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()
My Scripts and Functions: V1  V2
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

25 Aug 2014, 02:55

Wow great! I actually needed something like this... Thanks for sharing! :)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: WTSEnumProcesses() - Returns list of running processes

25 Aug 2014, 05:23

joedf wrote:Wow great! I actually needed something like this... Thanks for sharing! :)
lol, what did you need this for?

User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

25 Aug 2014, 08:23

I did some "test" projects... A so called memory cleaner, a "New process launch prevention" thingy, "task manager", bunch of Stuff :P
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

26 Aug 2014, 06:29

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:
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: WTSEnumProcesses() - Returns list of running processes

26 Aug 2014, 09:19

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.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

26 Sep 2014, 05:54

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
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Skrell
Posts: 302
Joined: 23 Jan 2014, 12:05

Re: WTSEnumProcesses() - Returns list of running processes

27 Sep 2014, 21:11

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 ?
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: WTSEnumProcesses() - Returns list of running processes

27 Sep 2014, 21:28

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.
Skrell
Posts: 302
Joined: 23 Jan 2014, 12:05

Re: WTSEnumProcesses() - Returns list of running processes

28 Sep 2014, 10:10

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 ?
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

06 May 2015, 09:13

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!
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

06 May 2015, 09:24

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
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

06 May 2015, 09:50

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
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

07 May 2015, 03:24

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
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Iomega0318
Posts: 83
Joined: 06 Apr 2015, 14:56
Location: Wolfforth, TX
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

07 May 2015, 14:39

Interesting, also great job :)
serg
Posts: 56
Joined: 21 Mar 2015, 05:33

Re: WTSEnumProcesses() - Returns list of running processes

04 Sep 2015, 08:38

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)
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: WTSEnumProcesses() - Returns list of running processes

05 Sep 2015, 17:38

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
}
User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

Re: WTSEnumProcesses() - Returns list of running processes

29 Oct 2022, 02:51

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
}
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 101 guests