process: get user name (like Task Manager)

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

process: get user name (like Task Manager)

18 Oct 2017, 20:13

This works but only gets the user name if it's me, it doesn't get LOCAL SERVICE/NETWORK SERVICE/SYSTEM like Task Manager does.

Note: to see more items in Task Manager, click 'Show processes from all users' at the bottom-left of the Processes tab.

[EDIT:] It did show those strings if I ran the script as Admin.

Code: Select all

;based on:
;How to get current username (non-admin) when running script as Admin? - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=21406

q:: ;list processes and user names
;current process
WinGet, vPID, PID, A
for oProcess in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessId = " vPID)
{
	VarSetCapacity(var, 24, 0), vref := ComObject(0x400C, &var)
	oProcess.GetOwner(vref, "")
	vOwner := vref[]
	MsgBox, % vOwner
}

;all processes
oArray := {}
for oProcess in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
{
	VarSetCapacity(var, 24, 0), vref := ComObject(0x400C, &var)
	oProcess.GetOwner(vref, "")
	vOwner := vref[]
	oArray[oProcess.ProcessId] := vOwner "`t" oProcess.Name

	;VarSetCapacity(var, 24, 0), vref := ComObject(0x400C, &var)
	;oProcess.GetOwnerSID(vref, "")
	;vOwnerSid := vref[]
	;oArray[oProcess.ProcessId] := vOwner "`t" vOwnerSID "`t" oProcess.Name
}
for vKey, vValue in oArray
	vOutput .= vKey "`t" vValue "`r`n"
oArray := ""
Clipboard := vOutput
MsgBox, % vOutput
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

19 Oct 2017, 01:41

see here -> https://github.com/jNizM/AHK_Process_Explorer

Code: Select all

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

#NoEnv
#SingleInstance Force
#Persistent

SetBatchLines -1

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

TaskManager := WTSEnumerateProcessesEx()

Gui, Margin, 5, 5
Gui, Add, ListView, xm ym w800 r20, % "ProcessName|PID|User Name"
for k, v in TaskManager
    LV_Add("", v.ProcessName, v.ProcessID, v.UserName)
LV_ModifyCol(1, 200), LV_ModifyCol(2, 80), LV_ModifyCol(3, 300)
Gui, Show, AutoSize
return

; ===============================================================================================================================

GuiClose:
ExitApp

; ===============================================================================================================================

WTSEnumerateProcessesEx()
{
    if (DllCall("wtsapi32\WTSEnumerateProcessesEx", "ptr", 0, "uint*", 1, "uint", 0xFFFFFFFE, "ptr*", buf, "uint*", TTL)) {
        addr := buf, WTS := []
        loop % TTL {
            WTS[A_Index, "ProcessID"]   := NumGet(addr + 4, "uint")
            WTS[A_Index, "ProcessName"] := StrGet(NumGet(addr + 8, "ptr"))
            LAS := LookupAccountSid(SID := NumGet(addr + 8 + (A_PtrSize), "ptr"))
            WTS[A_Index, "UserName"]    := (LAS.Name = "") ? "" : LAS.Domain "/" LAS.Name
            addr += 48 + (A_PtrSize * 2)
        }
        return WTS, DllCall("wtsapi32\WTSFreeMemoryEx", "int", 1, "ptr", buf, "uint", TTL)
    }
    return 0
}

LookupAccountSid(SID)
{
    DllCall("advapi32\LookupAccountSid", "ptr", 0, "ptr", SID, "ptr", 0, "uint*", sn, "ptr", 0, "uint*", sd, "uint*", 1)
    VarSetCapacity(n, sn * (A_IsUnicode ? 2 : 1), 0), VarSetCapacity(d, sd * (A_IsUnicode ? 2 : 1), 0)
    if (DllCall("advapi32\LookupAccountSid", "ptr", 0, "ptr", SID, "str", n, "uint*", sn, "str", d, "uint*", sd, "uint*", 1))
        return { Name: n, Domain: d }
    return 0
}

; ===============================================================================================================================
edit..
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: process: get user name (like Task Manager)

19 Oct 2017, 04:21

Many thanks jNizM.

- Very nice, it runs very fast, cf. my script, which is perhaps slowed down by using a WMI object.
- Like my script, you need to run as Admin, to see the usernames when it's not your username, otherwise you get a blank. (AHK Process Explorer shows blanks, this script shows 0s.)
- The results are slightly different to those of Task Manager, and it actually found some processes that Task Manager didn't.
- Note: AHK Process Explorer currently only works on AHK x64. (It says this on the GitHub page but I didn't notice it.)

[EDIT:] I thought I knew most of your scripts jNizM, but clearly not this one, a great find, cheers.
Last edited by jeeswg on 19 Oct 2017, 04:54, edited 4 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

19 Oct 2017, 04:25

Just change the return from 0 to ""

The better TaskManager -> Process Explorer (by Mark Russinovich from Sysinternals)

Will try to finish my ProcessExplorer..
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: process: get user name (like Task Manager)

19 Oct 2017, 04:28

My try:

Code: Select all

Process, Exist, dwm.exe
PID := ErrorLevel
MsgBox, % "process: dwm.exe`nPID: " . PID . "`nuser: " . GetProcessOwner(PID, "user", true)

Process, Exist, dllhost.exe
PID := ErrorLevel
MsgBox, % "process: dllhost.exe`nPID: " . PID . "`nowner: " . GetProcessOwner(PID, "owner", true)

GetProcessOwner(PID, value, runAsAdmin := false)  {
   static PROCESS_QUERY_INFORMATION := 0x400, TOKEN_QUERY := 0x8
        , TokenUser := 1, TokenOwner := 4, MAX_NAME := 32, isAdmin
    
   if (runAsAdmin && !isAdmin)
      IsAdminChecking(), SetDebugPrivilege(), isAdmin := true
        
   if !hProcess := DllCall("OpenProcess", UInt, PROCESS_QUERY_INFORMATION, UInt, false, UInt, PID, Ptr)
      Return ErrorHandling("OpenProcess")
   if !DllCall("Advapi32\OpenProcessToken", Ptr, hProcess, UInt, TOKEN_QUERY, PtrP, hToken)
      Return ErrorHandling("OpenProcessToken", hProcess)
   
   tokenType := value = "user" ? TokenUser : TokenOwner
   DllCall("Advapi32\GetTokenInformation", Ptr, hToken, Int, tokenType, Ptr, 0, Int, 0, UIntP, bites)
   VarSetCapacity(buff, bites, 0)
   if !DllCall("Advapi32\GetTokenInformation", Ptr, hToken, Int, tokenType, Ptr, &buff, Int, bites, UIntP, bites)
      Return ErrorHandling("GetTokenInformation", hProcess, hToken)
   
   VarSetCapacity(sName, MAX_NAME << !!A_IsUnicode, 0)
   VarSetCapacity(sDomainName, MAX_NAME << !!A_IsUnicode, 0)
   VarSetCapacity(szName, 4, 0), NumPut(MAX_NAME, szName)
   if !DllCall( "Advapi32\LookupAccountSid", Ptr, 0, Ptr, NumGet(buff), Str, sName, Ptr, &szName
                                           , Str, sDomainName, Ptr, &szName, IntP, SID_NAME_USE )
      Return ErrorHandling("LookupAccountSid", hProcess, hToken)
   DllCall("CloseHandle", Ptr, hProcess), DllCall("CloseHandle", Ptr, hToken)
   Return sName
}

ErrorHandling(function, hProcess := "", hToken := "")  {
   MsgBox, % "Failed: " . function . "`nerror: " . SysError()
   for k, v in [hProcess, hToken]
      ( v && DllCall("CloseHandle", Ptr, v) )
}

IsAdminChecking()  {
   restart := RegExMatch( DllCall("GetCommandLine", "str"), " /restart(?!\S)" )
   if !(A_IsAdmin || restart)  {
      try  {
         if A_IsCompiled
            Run *RunAs "%A_ScriptFullPath%" /restart
         else
            Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"
      }
      ExitApp
   }
   if (restart && !A_IsAdmin)
      MsgBox, Failed to run as admin!
}

SetDebugPrivilege(enable := true)  {
   static PROCESS_QUERY_INFORMATION := 0x400, TOKEN_ADJUST_PRIVILEGES := 0x20, SE_PRIVILEGE_ENABLED := 0x2
   
   hProc := DllCall("OpenProcess", UInt, PROCESS_QUERY_INFORMATION, Int, false, UInt, DllCall("GetCurrentProcessId"), Ptr)
   DllCall("Advapi32\OpenProcessToken", Ptr, hProc, UInt, TOKEN_ADJUST_PRIVILEGES, PtrP, token)
   
   DllCall("Advapi32\LookupPrivilegeValue", Ptr, 0, Str, "SeDebugPrivilege", Int64P, luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", Ptr, token, Int, !enable, Ptr, &TOKEN_PRIVILEGES, UInt, 0, Ptr, 0, Ptr, 0)
   res := A_LastError
   DllCall("CloseHandle", Ptr, token)
   DllCall("CloseHandle", Ptr, hProc)
   Return res  ; success — 0
}

SysError(ErrorNum = "")  {
   static FORMAT_MESSAGE_ALLOCATE_BUFFER := 0x100, FORMAT_MESSAGE_FROM_SYSTEM := 0x1000
   (ErrorNum = "" && ErrorNum := A_LastError)
   DllCall("FormatMessage", UInt, FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM
                          , UInt, 0, UInt, ErrorNum, UInt, 0, PtrP,  pBuff, UInt, 512, Str, "")
   Return (str := StrGet(pBuff)) ? str : ErrorNum
}
Last edited by teadrinker on 19 Oct 2017, 13:19, edited 1 time in total.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

19 Oct 2017, 04:51

Thanks for your input teadrinker
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: process: get user name (like Task Manager)

19 Oct 2017, 05:17

Cheers teadrinker.

Btw I like your solution for preparing Unicode/ANSI buffers (the third one).

Code: Select all

q::
MsgBox, % 260 * (!!A_IsUnicode+1)
MsgBox, % 260 * (A_IsUnicode?2:1)
MsgBox, % 260 << !!A_IsUnicode
return
Btw is it SetDebugPrivilege or SeDebugPrivilege, I think it's 'Se' rather than 'Set', always confused me that. I can't find any information on it, I even checked winnt.h, where a lot of constants begin 'SE_'. I could guess something like system environment, or security, but I don't know.

[EDIT:] One key bit of information, although that doesn't answer what 'SE' means.
c# - Is SeDebugPrivilege() api function the same as System.Diagnostics.Process.EnterDebugMode? - Stack Overflow
https://stackoverflow.com/questions/133 ... ess-enterd
For clarity, SeDebugPrivilege is not an API function, it's a privilege constant.
Last edited by jeeswg on 19 Oct 2017, 05:26, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

19 Oct 2017, 05:21

First time I saw the usage from size << !!A_IsUnicode was in some code from just me a few years ago
For my own code I just use size << 0x1 because I personally dont use ansi or x86

From winnt.h

Code: Select all

////////////////////////////////////////////////////////////////////////
//                                                                    //
//               NT Defined Privileges                                //
//                                                                    //
////////////////////////////////////////////////////////////////////////

#define SE_CREATE_TOKEN_NAME                         TEXT("SeCreateTokenPrivilege")
#define SE_ASSIGNPRIMARYTOKEN_NAME                   TEXT("SeAssignPrimaryTokenPrivilege")
#define SE_LOCK_MEMORY_NAME                          TEXT("SeLockMemoryPrivilege")
#define SE_INCREASE_QUOTA_NAME                       TEXT("SeIncreaseQuotaPrivilege")
#define SE_UNSOLICITED_INPUT_NAME                    TEXT("SeUnsolicitedInputPrivilege")
#define SE_MACHINE_ACCOUNT_NAME                      TEXT("SeMachineAccountPrivilege")
#define SE_TCB_NAME                                  TEXT("SeTcbPrivilege")
#define SE_SECURITY_NAME                             TEXT("SeSecurityPrivilege")
#define SE_TAKE_OWNERSHIP_NAME                       TEXT("SeTakeOwnershipPrivilege")
#define SE_LOAD_DRIVER_NAME                          TEXT("SeLoadDriverPrivilege")
#define SE_SYSTEM_PROFILE_NAME                       TEXT("SeSystemProfilePrivilege")
#define SE_SYSTEMTIME_NAME                           TEXT("SeSystemtimePrivilege")
#define SE_PROF_SINGLE_PROCESS_NAME                  TEXT("SeProfileSingleProcessPrivilege")
#define SE_INC_BASE_PRIORITY_NAME                    TEXT("SeIncreaseBasePriorityPrivilege")
#define SE_CREATE_PAGEFILE_NAME                      TEXT("SeCreatePagefilePrivilege")
#define SE_CREATE_PERMANENT_NAME                     TEXT("SeCreatePermanentPrivilege")
#define SE_BACKUP_NAME                               TEXT("SeBackupPrivilege")
#define SE_RESTORE_NAME                              TEXT("SeRestorePrivilege")
#define SE_SHUTDOWN_NAME                             TEXT("SeShutdownPrivilege")
#define SE_DEBUG_NAME                                TEXT("SeDebugPrivilege")
#define SE_AUDIT_NAME                                TEXT("SeAuditPrivilege")
#define SE_SYSTEM_ENVIRONMENT_NAME                   TEXT("SeSystemEnvironmentPrivilege")
#define SE_CHANGE_NOTIFY_NAME                        TEXT("SeChangeNotifyPrivilege")
#define SE_REMOTE_SHUTDOWN_NAME                      TEXT("SeRemoteShutdownPrivilege")
#define SE_UNDOCK_NAME                               TEXT("SeUndockPrivilege")
#define SE_SYNC_AGENT_NAME                           TEXT("SeSyncAgentPrivilege")
#define SE_ENABLE_DELEGATION_NAME                    TEXT("SeEnableDelegationPrivilege")
#define SE_MANAGE_VOLUME_NAME                        TEXT("SeManageVolumePrivilege")
#define SE_IMPERSONATE_NAME                          TEXT("SeImpersonatePrivilege")
#define SE_CREATE_GLOBAL_NAME                        TEXT("SeCreateGlobalPrivilege")
#define SE_TRUSTED_CREDMAN_ACCESS_NAME               TEXT("SeTrustedCredManAccessPrivilege")
#define SE_RELABEL_NAME                              TEXT("SeRelabelPrivilege")
#define SE_INC_WORKING_SET_NAME                      TEXT("SeIncreaseWorkingSetPrivilege")
#define SE_TIME_ZONE_NAME                            TEXT("SeTimeZonePrivilege")
#define SE_CREATE_SYMBOLIC_LINK_NAME                 TEXT("SeCreateSymbolicLinkPrivilege")
#define SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME    TEXT("SeDelegateSessionUserImpersonatePrivilege")
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: process: get user name (like Task Manager)

19 Oct 2017, 05:25

I think, "se" is security. But in SetDebugPrivilege "set" is the verb. :)
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

20 Oct 2017, 03:50

Rewritten my code for ProcessExplorer
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: process: get user name (like Task Manager)

20 Oct 2017, 04:12

jNizM wrote:Rewritten my code for ProcessExplorer
Tested it on Windows 10, it works slightly incorrectly:
Spoiler
Some usernames does not display, CPU usage column is blank.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

20 Oct 2017, 04:58

CPU usage is in todo.

UserName depends on Process.UserSid
https://github.com/jNizM/AHK_Process_Ex ... r.ahk#L202 (202 - 205)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: process: get user name (like Task Manager)

20 Oct 2017, 05:28

Than I will implement your way =)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: process: get user name (like Task Manager)

20 Oct 2017, 08:37

AFAICS both approaches can only get the username every time if run as Admin.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: process: get user name (like Task Manager)

20 Oct 2017, 08:58

Nothing can be done. If the process is elevated, but the script is not, OpenProcess fails.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: process: get user name (like Task Manager)

20 Oct 2017, 09:45

Of course, the script might, instead of reloading itself, starting new its elevated instance, and getting info from it.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Billykid, divanebaba and 172 guests