Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Dllcall for ShellExecuteEx / ShellExecuteExA


  • Please log in to reply
5 replies to this topic
daorc
  • Members
  • 177 posts
  • Last active:
  • Joined: 18 Oct 2006
Hello,

I'm afraid I'm not very good at using dllcall! I've been using this to run “setup.exe” with admin privileges, and it works fine:

DllCall("shell32\ShellExecuteA", uint, 0, str, "RunAs", str, A_ScriptDir "\SETUP.exe", str, PARAMS , str, A_WorkingDir, int, 1)

This is quite similar to the “run” command, but I'd like to be able to replicate “runwait”. So I'd like to find out the Process ID of the setup.exe that's just been run with this command, and then just use:

process,wait,%PID%

. … but I don't know how to get the PID from ShellExecuteEx. I've looked at using ShellExecuteExA, because that looks like it might be able to return the PID, but I don't understand what's on MSDN, or how to turn this into a dllcall.

Relevant links:
http://msdn.microsof...153(VS.85).aspx
http://msdn.microsof...4(v=VS.85).aspx

Please help me! :)

a_h_k
  • Members
  • 685 posts
  • Last active: Sep 28 2015 12:32 AM
  • Joined: 02 Feb 2008
Have you considered using other dll calls? Perhaps Parent ProcessID, ProcessName, ProcessThreadCount (uses a few dll's & user-defined functions)

:?:

daorc
  • Members
  • 177 posts
  • Last active:
  • Joined: 18 Oct 2006
Thanks, but each of those is either referring to the script's process or requires a process ID to be sent to it. What I need to do is determine the process ID of the program just launched (with ShellExxecuteA or ShellExecuteExA). So I need to get the process ID returned from those DLL calls. Any ideas?

Cheers

a_h_k
  • Members
  • 685 posts
  • Last active: Sep 28 2015 12:32 AM
  • Joined: 02 Feb 2008
Try something like this...
; Set the structure size (ShellExecuteEx will return the data in this)
VarSetCapacity(LPSHELLEXECUTEINFO, 64, 0)  ;APPROX length = 16 x 4 bytes = 64 bytes

; Call the function
error := DllCall("shell32\ShellExecuteExA", UInt, &LPSHELLEXECUTEINFO, Int)

; Fetch the required data (PID)
ProcessID := NumGet(LPSHELLEXECUTEINFO, 60, "UInt")  ;APPROX pos of "HANDLE hProcess" = 15 x 4 = 60
(haven't got time right now to test)

From SHELLEXECUTEINFO Structure page...

typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;
ULONG fMask;
HWND hwnd;
LPCTSTR lpVerb;
LPCTSTR lpFile;
LPCTSTR lpParameters;
LPCTSTR lpDirectory;
int nShow;
HINSTANCE hInstApp;
LPVOID lpIDList;
LPCTSTR lpClass;
HKEY hkeyClass;
DWORD dwHotKey;
union {
HANDLE hIcon;
HANDLE hMonitor;
} DUMMYUNIONNAME;
HANDLE hProcess;
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;

See also the Help .. Structures and Arrays

daorc
  • Members
  • 177 posts
  • Last active:
  • Joined: 18 Oct 2006
Thank you so much! I had been getting there slowly, but hadn't got anywhere near a 3-line solution yet! By the way, for anyone else wanting to learn about this, I found these links really useful:

http://www.autohotke...topic35843.html
http://www.autohotke...pic.php?t=54246

Thanks again!

daorc
  • Members
  • 177 posts
  • Last active:
  • Joined: 18 Oct 2006
A working example. I know some of the lines are not strictly necessary, but it helps me understand it :)

LPSHELLEXECUTEINFO_size=60 ;15members * 4bytes/member

	VarSetCapacity(LPSHELLEXECUTEINFO,LPSHELLEXECUTEINFO_size, 0)

	cbSize=%LPSHELLEXECUTEINFO_size%
	NumPut(cbSize, LPSHELLEXECUTEINFO, 0, "UInt") ;cbSize 

	fMask=64 ;Required in order for “hProcess” to be set by the DLL.  It must be “SEE_MASK_NOCLOSEPROCESS” (0x00000040 [=64])
	NumPut(fMask, LPSHELLEXECUTEINFO, 4, "UInt") ;fMask

	hwnd=0
	NumPut(hwnd, LPSHELLEXECUTEINFO, 8, "UInt") ;hwnd

	lpVerb=RunAs
	NumPut(&lpVerb, LPSHELLEXECUTEINFO, 12, "UInt") ;lpVerb

	lpFile=%A_ScriptFullPath%
	NumPut(&lpFile, LPSHELLEXECUTEINFO, 16, "UInt") ;lpFile

	lpParameters=%PARAMS%
	NumPut(&lpParameters, LPSHELLEXECUTEINFO, 20, "UInt") ;lpParameters

	lpDirectory=%A_WorkingDir%
	NumPut(&lpDirectory, LPSHELLEXECUTEINFO, 24, "UInt") ;lpDirectory

	nShow=1 ;required, but interpreted by new launch of this script, so can just be ignored
	NumPut(nShow, LPSHELLEXECUTEINFO, 28, "UInt") ;nshow ;required, but interpreted by new launch of setup.exe, so can just be ignored

	;get process handle
	DllCall("shell32\ShellExecuteExA", UInt, &LPSHELLEXECUTEINFO) ;structures must be "UInt" ;http://msdn.microsoft.com/en-us/library/bb762154(v=VS.85).aspx    http://www.autohotkey.com/forum/viewtopic.php?t=54246    http://www.autohotkey.com/forum/topic35843.html
	Process_handle:=NumGet(LPSHELLEXECUTEINFO,56)
	
	;get process ID from handle
	Process_ID:=DllCall("Kernel32\GetProcessId", UInt,Process_handle) ;http://msdn.microsoft.com/en-us/library/ms683215(VS.85).aspx