|
-
Jan 1st, 2022, 01:06 PM
#1
Thread Starter
Member
[RESOLVED] Need everyone's help: Get the command line of a process on Windows 7 64-bit
Hi everyone, I use the below code to get the command line of a process, it works on both Windows 7 32-bit and Windows 7 64-bit. However, on Windows 7 64-bit, only some 32-bit applications get the information (eg Notepad), the rest not return anything (eg WordPad).
Can someone please help me with this problem?
Sincerely thank you,
FerrMask
CommandLinePEB.zip
-
Jan 1st, 2022, 01:14 PM
#2
Re: Need everyone's help: Get the command line of a process on Windows 7 64-bit
You use wrong method. The simple method is:
Code:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_Process")
For Each objItem in colItems
Wscript.Echo objItem.Name
Wscript.Echo objItem.CommandLine
Next
-
Jan 1st, 2022, 03:20 PM
#3
Re: Need everyone's help: Get the command line of a process on Windows 7 64-bit
The 64-bit aware approach using PEB:
Code:
' // Get command line of process
' // 64-bit compatible
' // By The trick
Option Explicit
Private Const ProcessBasicInformation As Long = 0
Private Const SystemProcessInformation As Long = 5
Private Const PROCESS_QUERY_LIMITED_INFORMATION As Long = &H1000
Private Const PROCESS_VM_READ As Long = &H10
Private Const SE_PRIVILEGE_ENABLED As Long = 2
Private Const TOKEN_ADJUST_PRIVILEGES As Long = &H20
Private Const SE_DEBUG_NAME As String = "SeDebugPrivilege"
Private Type UNICODE_STRING
Length As Integer
MaxLength As Integer
lpBuffer As Long
End Type
Private Type UNICODE_STRING64
Length As Integer
MaxLength As Integer
lPad As Long
lpBuffer As Currency
End Type
Private Type PROCESS_BASIC_INFORMATION
ExitStatus As Long
PebBaseAddress As Long
AffinityMask As Long
BasePriority As Long
UniqueProcessId As Long
InheritedFromUniqueProcessId As Long
End Type
Private Type PROCESS_BASIC_INFORMATION64
ExitStatus As Long
Reserved0 As Long
PebBaseAddress As Currency
AffinityMask As Currency
BasePriority As Long
Reserved1 As Long
uUniqueProcessId As Currency
uInheritedFromUniqueProcessId As Currency
End Type
Private Declare Function GetModuleHandle Lib "kernel32" _
Alias "GetModuleHandleW" ( _
ByVal lpModuleName As Long) As OLE_HANDLE
Private Declare Function GetProcAddress Lib "kernel32" ( _
ByVal hModule As OLE_HANDLE, _
ByVal lpProcName As String) As Long
Private Declare Function IsWow64Process Lib "kernel32" ( _
ByVal hProcess As OLE_HANDLE, _
ByRef lpWow64Process As Long) As Long
Private Declare Function NtQueryInformationProcess Lib "ntdll" ( _
ByVal ProcessHandle As OLE_HANDLE, _
ByVal InformationClass As Long, _
ByRef ProcessInformation As Any, _
ByVal ProcessInformationLength As Long, _
ByRef ReturnLength As Long) As Long
Private Declare Function NtQuerySystemInformation Lib "ntdll" ( _
ByVal SystemInformationClass As Long, _
ByRef ProcessInformation As Any, _
ByVal ProcessInformationLength As Long, _
ByRef ReturnLength As Long) As Long
Private Declare Function NtWow64QueryInformationProcess64 Lib "ntdll" ( _
ByVal hProcess As OLE_HANDLE, _
ByVal ProcessInformationClass As Long, _
ByRef pProcessInformation As Any, _
ByVal ProcessInformationLength As Long, _
ByRef puReturnLength As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" ( _
ByVal hProcess As OLE_HANDLE, _
ByVal lpBaseAddress As Long, _
ByRef lpBuffer As Any, _
ByVal nSize As Long, _
ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function NtWow64ReadVirtualMemory64 Lib "ntdll" ( _
ByVal hProcess As OLE_HANDLE, _
ByVal BaseAddress As Currency, _
ByRef Buffer As Any, _
ByVal BufferLengthL As Long, _
ByVal BufferLengthH As Long, _
ByRef ReturnLength As Currency) As Long
Private Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As OLE_HANDLE
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As OLE_HANDLE) As Long
Private Declare Function SysAllocStringByteLen Lib "oleaut32" ( _
ByRef psz As Any, _
ByVal lLen As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32" _
Alias "LookupPrivilegeValueW" ( _
ByVal lpSystemName As Long, _
ByVal lpName As Long, _
ByRef lpLuid As Any) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32" ( _
ByVal TokenHandle As OLE_HANDLE, _
ByVal DisableAllPrivileges As Long, _
ByRef NewState As Any, _
ByVal BufferLength As Long, _
ByRef PreviousState As Any, _
ByRef ReturnLength As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As OLE_HANDLE
Private Declare Function OpenProcessToken Lib "advapi32.dll" ( _
ByVal ProcessHandle As OLE_HANDLE, _
ByVal DesiredAccess As Long, _
ByRef TokenHandle As OLE_HANDLE) As Long
Private Declare Sub GetMem4 Lib "msvbvm60" (Src As Any, Dst As Any)
Private Declare Sub PutMem4 Lib "msvbvm60" (Dst As Any, ByVal lVal As Long)
Private Sub Main()
Dim bProcInfo() As Byte
Dim lSize As Long
Dim lNextOffset As Long
Dim lCurOffset As Long
Dim lPID As Long
Dim hProcess As OLE_HANDLE
Dim sName As String
Dim pStr As Long
SetPrivilege SE_DEBUG_NAME, True
lSize = 1024
Do
ReDim bProcInfo(lSize - 1)
Loop While NtQuerySystemInformation(SystemProcessInformation, bProcInfo(0), lSize, lSize)
Do
lCurOffset = lCurOffset + lNextOffset
GetMem4 bProcInfo(lCurOffset + &H44), lPID
hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION Or PROCESS_VM_READ, 0, lPID)
If hProcess Then
sName = vbNullString
GetMem4 bProcInfo(lCurOffset + &H3C), pStr
PutMem4 ByVal VarPtr(sName), SysAllocStringByteLen(ByVal pStr, bProcInfo(lCurOffset + &H38) Or &H100& * bProcInfo(lCurOffset + &H39))
On Error GoTo close_handle
Debug.Print sName, lPID, GetCommandLineOfProcess(hProcess)
close_handle:
CloseHandle hProcess
End If
GetMem4 bProcInfo(lCurOffset), lNextOffset
Loop While lNextOffset
End Sub
Public Function GetCommandLineOfProcess( _
ByVal hProcess As OLE_HANDLE) As String
Dim tPEB32 As PROCESS_BASIC_INFORMATION
Dim tPEB64 As PROCESS_BASIC_INFORMATION64
Dim tCMDLine As UNICODE_STRING
Dim tCMDLine64 As UNICODE_STRING64
Dim pParam As Long
Dim pParam64 As Currency
If Is32BitProcess(hProcess) Then
If NtQueryInformationProcess(hProcess, ProcessBasicInformation, tPEB32, LenB(tPEB32), 0) < 0 Then
Err.Raise 7
End If
If ReadProcessMemory(hProcess, tPEB32.PebBaseAddress + &H10, pParam, LenB(pParam), 0) = 0 Then
Err.Raise 7
End If
If ReadProcessMemory(hProcess, pParam + &H40, tCMDLine, LenB(tCMDLine), 0) = 0 Then
Err.Raise 7
End If
If tCMDLine.Length > 0 Then
GetCommandLineOfProcess = Space$(tCMDLine.Length \ 2)
If ReadProcessMemory(hProcess, tCMDLine.lpBuffer, ByVal StrPtr(GetCommandLineOfProcess), tCMDLine.Length, 0) = 0 Then
Err.Raise 7
End If
End If
Else
If NtWow64QueryInformationProcess64(hProcess, ProcessBasicInformation, tPEB64, LenB(tPEB64), 0) < 0 Then
Err.Raise 7
End If
If NtWow64ReadVirtualMemory64(hProcess, tPEB64.PebBaseAddress + 0.0032@, pParam64, Len(pParam64), 0, 0) < 0 Then
Err.Raise 7
End If
If NtWow64ReadVirtualMemory64(hProcess, pParam64 + 0.0112@, tCMDLine64, Len(tCMDLine64), 0, 0) < 0 Then
Err.Raise 7
End If
If tCMDLine64.Length > 0 Then
GetCommandLineOfProcess = Space$(tCMDLine64.Length \ 2)
If NtWow64ReadVirtualMemory64(hProcess, tCMDLine64.lpBuffer, ByVal StrPtr(GetCommandLineOfProcess), tCMDLine64.Length, 0, 0) < 0 Then
Err.Raise 7
End If
End If
End If
End Function
Public Function Is32BitProcess( _
ByVal hProcess As OLE_HANDLE) As Boolean
Static s_bHasWow64 As Boolean
Static s_bInit As Boolean
Dim lWow64 As Long
If Not s_bInit Then
s_bHasWow64 = GetProcAddress(GetModuleHandle(StrPtr("kernel32")), "IsWow64Process")
s_bInit = True
End If
If s_bHasWow64 Then
If IsWow64Process(hProcess, lWow64) = 0 Then
Err.Raise 7
End If
Is32BitProcess = lWow64
Else
Is32BitProcess = True
End If
End Function
Public Function SetPrivilege( _
ByVal sPrivilege As String, _
ByVal bEnable As Boolean) As Boolean
Dim bPriv(15) As Byte
Dim hToken As OLE_HANDLE
If OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken) = 0 Then
Exit Function
End If
If LookupPrivilegeValue(0, StrPtr(sPrivilege), bPriv(4)) = 0 Then
CloseHandle hToken
Exit Function
End If
bPriv(0) = 1
If bEnable Then
bPriv(12) = SE_PRIVILEGE_ENABLED
End If
If AdjustTokenPrivileges(hToken, 0, bPriv(0), 0, ByVal 0&, 0) = 0 Then
CloseHandle hToken
Exit Function
End If
CloseHandle hToken
SetPrivilege = True
End Function
BTW you can also use ProcessCommandLineInformation info class since win 8.1
Last edited by The trick; Jan 1st, 2022 at 03:25 PM.
-
Jan 2nd, 2022, 03:33 AM
#4
Thread Starter
Member
 Originally Posted by The trick
The 64-bit aware approach using PEB...
Thank you very much. Wishing you and your family a very happy, healthy and prosperous new year
Last edited by ferrmask; Jan 2nd, 2022 at 03:40 AM.
-
May 20th, 2026, 07:21 AM
#5
Fanatic Member
Re: [RESOLVED] Need everyone's help: Get the command line of a process on Windows 7 6
I will try to modify this to get the command line by PID. Not all processes.
-
May 20th, 2026, 03:59 PM
#6
Re: [RESOLVED] Need everyone's help: Get the command line of a process on Windows 7 6
You'd just go directly to get command line
Code:
Function GetByPid(ByVal lPID As Long) As String
Dim hProcess As OLE_HANDLE: hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION Or PROCESS_VM_READ, 0, lPID)
GetByPid = GetCommandLineOfProcess(hProcess)
CloseHandle hProcess
End Function
-
May 22nd, 2026, 02:17 PM
#7
Member
Re: [RESOLVED] Need everyone's help: Get the command line of a process on Windows 7 6
Code:
Function ParseCommandLine() As Collection
Dim args As New Collection
Dim s As String:
Dim token As String
Dim inQuotes As Boolean
Dim i As Long, ch As String
s = Trim$(Command$())
For i = 1 To Len(s)
ch = Mid$(s, i, 1)
Select Case ch
Case """"
inQuotes = Not inQuotes
Case " "
If inQuotes Then
token = token & ch
Else
If Len(token) > 0 Then
args.Add token
token = ""
End If
End If
Case Else
token = token & ch
End Select
Next
If Len(token) > 0 Then args.Add token
Set ParseCommandLine = args
End Function
Sub Main()
Dim args As Collection
Set args = ParseCommandLine()
Dim a
For Each a In args
Debug.Print a
Next
End Sub
-
May 23rd, 2026, 09:15 AM
#8
Re: [RESOLVED] Need everyone's help: Get the command line of a process on Windows 7 6
There is a standard OS provided CommandLineToArgvW API which can properly parse Command$ the way every utility would do and can be used in VB6 like this SplitArgs function.
cheers,
</wqw>
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|