AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

GetCommandLine
Goto page 1, 2  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Mon Feb 12, 2007 3:56 pm    Post subject: GetCommandLine Reply with quote

This retrieves a start-up command-line of an application, once getting PID of it. If an application is an interactive service, then need an Debug privilege which I omitted for simplicity. If an application is a non-interactive service, then have to rely on other means.

Code:

/*
Process, Exist, myprog.exe
pid := ErrorLevel
*/

; Replace the WinTitle with the correct one
WinGet, pid, PID, ahk_class TTOTAL_CMD

VarSetCapacity(sFilePath, 260)
VarSetCapacity(sCmdLine, 512)

pFunc := DllCall("GetProcAddress"
   , "Uint", DllCall("GetModuleHandle", "str", "kernel32.dll")
   , "str", "GetCommandLineA")

hProc := DllCall("OpenProcess", "Uint", 0x043A, "int", 0, "Uint", pid)

hThrd := DllCall("CreateRemoteThread", "Uint", hProc, "Uint", 0, "Uint", 0
   , "Uint", pFunc, "Uint", 0, "Uint", 0, "Uint", 0)

DllCall("WaitForSingleObject", "Uint", hThrd, "Uint", 0xFFFFFFFF)
DllCall("GetExitCodeThread", "Uint", hThrd, "UintP", pcl)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pcl, "str", sCmdLine, "Uint", 512, "Uint", 0)

DllCall("psapi\GetModuleFileNameExA", "Uint", hProc, "Uint", 0, "str", sFilePath, "Uint", 260)
; DllCall("psapi\GetProcessImageFileNameA", "Uint", hProc, "str", sFilePath, "Uint", 281)

DllCall("CloseHandle", "Uint", hThrd)
DllCall("CloseHandle", "Uint", hProc)

MsgBox % sFilePath . " | " . sCmdLine



Last edited by Sean on Tue Feb 13, 2007 1:38 pm; edited 2 times in total
Back to top
View user's profile Send private message
Grumpy
Guest





PostPosted: Mon Feb 12, 2007 4:30 pm    Post subject: Reply with quote

Mmm, it was already there: process list+file names+command lines but it has other features there that might not be wanted, so it is nice to have it isolated. Thanks.
Back to top
carsong



Joined: 14 Oct 2006
Posts: 18

PostPosted: Tue Feb 13, 2007 11:24 am    Post subject: Re: GetCommandLine Reply with quote

Sean wrote:
This retrieves a start-up command-line of an application, once getting PID of it.


This helps a lot! Thanks!
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7183

PostPosted: Wed Nov 19, 2008 12:01 am    Post subject: Re: GetCommandLine Reply with quote

Dear Sean, Smile

You wrote:
If an application is an interactive service, then need an Debug privilege which I omitted for simplicity.


What happens to script/sCmdLine if my script unknowingly uses the PID of a Service ?

Smile
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Wed Nov 19, 2008 10:37 am    Post subject: Re: GetCommandLine Reply with quote

SKAN wrote:
What happens to script/sCmdLine if my script unknowingly uses the PID of a Service ?

Most of the DllCall()'s in the code will (silently) fail, without Debug privilege.
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7183

PostPosted: Wed Nov 19, 2008 10:41 am    Post subject: Reply with quote

Thank you Sean Smile

One more help please. Have I wrapped it right?

Code:
GetCommandLine( PID ) { ;  by Sean          www.autohotkey.com/forum/viewtopic.php?t=16575
 Static pFunc
 If ! ( hProcess := DllCall( "OpenProcess", UInt,0x043A, Int,0, UInt, PID ) )
        Return 
 If pFunc=
    pFunc := DllCall( "GetProcAddress", UInt
           , DllCall( "GetModuleHandle", Str,"kernel32.dll" ), Str,"GetCommandLineA" )
 hThrd := DllCall( "CreateRemoteThread", UInt,hProcess, UInt,0, UInt,0, UInt,pFunc, UInt,0
        , UInt,0, UInt,0 ),  DllCall( "WaitForSingleObject", UInt,hThrd, UInt,0xFFFFFFFF )
 DllCall( "GetExitCodeThread", UInt,hThrd, UIntP,pcl ), VarSetCapacity( sCmdLine,512 )
 DllCall( "ReadProcessMemory", UInt,hProcess, UInt,pcl, Str,sCmdLine, UInt,512, UInt,0 )
 DllCall( "CloseHandle", UInt,hThrd ), DllCall( "CloseHandle", UInt,hProcess )
Return sCmdLine
}

SetDebugPrivilege() {
 ;PROCESS_QUERY_INFORMATION=0x400, TOKEN_ADJUST_PRIVILEGES=0x20, SE_PRIVILEGE_ENABLED:=0x2
 hProcess := DllCall( "OpenProcess", UInt,0x400,Int,0,UInt,DllCall("GetCurrentProcessId"))
 DllCall( "Advapi32.dll\LookupPrivilegeValueA", UInt,0, Str,"SeDebugPrivilege", UIntP,lu )
  ; TOKEN_PRIVILEGES Structure : www.msdn.microsoft.com/en-us/library/aa379630(VS.85).aspx
 VarSetCapacity( TP,16,0), NumPut( 1,TP,0,4 ),  NumPut( lu,TP,4,8 ), NumPut( 0x2,TP,12,4 )
 DllCall( "Advapi32.dll\OpenProcessToken", UInt,hProcess, UInt,0x20, UIntP,hToken )
 Result :=  DllCall( "Advapi32.dll\AdjustTokenPrivileges"
                 , UInt,hToken, UInt,0, UInt,&TP, UInt,0, UInt,0, UInt,0 )
 DllCall( "CloseHandle", UInt,hProcess ), DllCall( "CloseHandle", UInt,hToken )
Return Result
}

SetDebugPrivilege()
MsgBox, % GetCommandLine( DllCall( "GetCurrentProcessId" ) )
Process, Exist, svchost.exe
MsgBox,0, %errorLevel%, % GetCommandLine( errorLevel )


Edit 2009-06-22: Added DelimitParameters()

The following function can convert the obtained command line into pipe delimited string to ease Loop, Parse or StringSplit

Code:
DelimitParameters( CommandLine,D="|" ) {     ; Supplementary function for GetCommandLine()
 tempVar := CommandLine           ; www.autohotkey.com/forum/viewtopic.php?p=232199#232199
 Loop {
 StringReplace,tempVar,tempVar,%Param%
 CommandLine := DllCall( "shlwapi\PathGetArgsA", Str,CommandLine,Str )
 StringReplace,Param,tempVar,%CommandLine%
 DllCall( "shlwapi\PathUnquoteSpacesA", Str,Param )
 IfEqual,Param,,Return SubStr(DelimitedString,2)
 DelimitedString = %DelimitedString%%D%%Param%
}}


Last edited by SKAN on Mon Jun 22, 2009 9:53 am; edited 2 times in total
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Wed Nov 19, 2008 12:31 pm    Post subject: Reply with quote

SKAN wrote:
Have I wrapped it right?

Yes, looks fine to me.
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7183

PostPosted: Wed Nov 19, 2008 12:40 pm    Post subject: Reply with quote

I could not grasp much from shimanov's GetRemoteCommandLine() and then saw your comment.
Thanks for sharing this wonderful code Sean.

Smile
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Wed Nov 19, 2008 1:05 pm    Post subject: Reply with quote

SKAN wrote:
I could not grasp much from shimanov's GetRemoteCommandLine() and then saw your comment.

Oh, my comment there was not correct. Looks like he tracked down the procedures of GetCommandLineA in the Debugger. As it's an implementation detail, relying on it should be the last choice.
BTW, my preferred method is indeed utilizing PEB, but it relies on the undocumented features unfortunately.
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7183

PostPosted: Wed Nov 19, 2008 1:42 pm    Post subject: Reply with quote

Sean wrote:
As it's an implementation detail, relying on it should be the last choice.


er.. I intend to use this only on all running AHK instances.. Is there a way to ascertain if compiled AHK is running as a service ?
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Wed Nov 19, 2008 2:27 pm    Post subject: Reply with quote

SKAN wrote:
Sean wrote:
As it's an implementation detail, relying on it should be the last choice.
er.. I intend to use this only on all running AHK instances..

I meant it only for GetRemoteCommandLine function. APIs and features my code used are all well-documented (although there is one loop-hole in the code: stack-mismatch after the call in the remote thread).

Quote:
Is there a way to ascertain if compiled AHK is running as a service?

The first one hitting me is retrieving the parent process (identifier) of the target process and checking if it's services.exe, if it's what you meant by service. It can be done using CreateToolhelp32Snapshot and Process32First/Process32Next, with Debug privilege enabled.
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7183

PostPosted: Wed Nov 19, 2008 3:18 pm    Post subject: Reply with quote

Sean wrote:
The first one hitting me is retrieving the parent process (identifier) of the target process and checking if it's services.exe, if it's what you meant by service. It can be done using CreateToolhelp32Snapshot and Process32First/Process32Next, with Debug privilege enabled.


Search reveals there are example calls already posted. Thank you very much for the pointer.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Wed Nov 19, 2008 3:48 pm    Post subject: Reply with quote

SKAN wrote:
Search reveals there are example calls already posted. Thank you very much for the pointer.

After reading your post more carefully, I now noticed this:
Quote:
only on all running AHK instances

As AHK can't be started as a service by itself, meaning that AHK can't be a (direct) child process of services.exe, I guess what you're really after is obtaining the user's name of a process and checking if it's NT AUTHORITY/SYSTEM. If turned out so, may use OpenProcess -> OpenProcessToken -> GetTokenInformation -> LookupAccountSid.
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 7183

PostPosted: Wed Nov 19, 2008 4:08 pm    Post subject: Reply with quote

Sean wrote:
what you're really after is obtaining the user's name of a process and checking if it's NT AUTHORITY/SYSTEM.


Almost exactly, except I thought of comparing it to A_Username. Would it not work? Rolling Eyes

Quote:
may use OpenProcess -> OpenProcessToken -> GetTokenInformation -> LookupAccountSid.


Thank you.. That looks simple.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2204

PostPosted: Wed Nov 19, 2008 4:34 pm    Post subject: Reply with quote

SKAN wrote:
Almost exactly, except I thought of comparing it to A_Username. Would it not work? Rolling Eyes

It depends. If want to rule out not only services but also all ones run as other accounts than the current user, then A_UserName should be used than SYSTEM.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group