Page 1 of 1
Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 4:25 pm
by jacky
This is the .ahk code:
Code: Select all
ComObjCreate("Shell.Application").Windows.FindWindowSW(0 , 0 , 8 , 0 , 1).Document.Application.ShellExecute("""c:\windows\notepad.exe""")
Can anybody convert this to PB code please?
So far it's the only reliable way I've found (and in this case by far the shortest) that is able to run a program with user rights if the calling program is running as admin...
All the solutions I've found here:
viewtopic.php?f=5&t=71575
produce only fully elevated ones...
Re: Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 4:56 pm
by Mijikai
Try:
Code: Select all
runas /trustlevel:0x20000 notepad.exe
Or:
Or:
Re: Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 6:48 pm
by jacky
Thanks for the suggestions, Mijikai.
01. Doesn't work, notepad will be elevated
03. That would require a task (which needs to be setup beforehand)
02. Works in a command prompt, but do you have any idea how to pass arguments to notepad in this case?
Code: Select all
explorer.exe ""c:\windows\notepad.exe" "D:\some file.txt""
explorer.exe '"c:\windows\notepad.exe" "D:\some file.txt"'
Both don't work as expected.
It's easy to do it with the COM code, though:
Code: Select all
ComObjCreate("Shell.Application").Windows.FindWindowSW(0 , 0 , 8 , 0 , 1).Document.Application.ShellExecute("""c:\windows\notepad.exe""", """D:\some text file.txt""")
Re: Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 7:54 pm
by fryquez
Takes a bit more Code in PureBasic
Code: Select all
EnableExplicit
Import "Uuid.Lib"
IID_IShellFolderViewDual
CLSID_ShellWindows
IID_IShellWindows
IID_IShellView
SID_STopLevelBrowser
IID_IShellBrowser
IID_IDispatch
IID_IShellDispatch2
IID_IServiceProvider
EndImport
Macro SUCCEEDED_(HRESULT)
(HRESULT & $80000000 = 0)
EndMacro
Procedure IUnknown_QueryService(*punk.IUnknown, guidService, riid, *ppvOut.Integer)
*ppvOut\i = 0
Protected.IServiceProvider *ISP
Protected hr.l = *punk\QueryInterface(@IID_IServiceProvider, @*ISP)
If Not SUCCEEDED_(hr)
ProcedureReturn #E_NOTIMPL
Else
hr = *ISP\QueryService(guidService, riid, @*ppvOut\i)
*ISP\Release()
EndIf
ProcedureReturn hr
EndProcedure
Procedure GetShellViewForDesktop(riid, *ppv.Integer)
*ppv\i = 0
Protected.IShellWindows *psw
Protected hr.l = CoCreateInstance_(@CLSID_ShellWindows, #Null, #CLSCTX_LOCAL_SERVER, @IID_IShellWindows, @*psw)
If SUCCEEDED_(hr)
Protected hwnd
Protected.IDispatch *pdisp
Protected.VARIANT vEmpty
#SWC_DESKTOP = 8
#SWFO_NEEDDISPATCH = 1
hr = *psw\FindWindowSW(@vEmpty, @vEmpty, #SWC_DESKTOP, @hwnd, #SWFO_NEEDDISPATCH, @*pdisp)
If #S_OK = hr
Protected.IShellBrowser *psb
hr = IUnknown_QueryService(*pdisp, @SID_STopLevelBrowser, @IID_IShellBrowser, @*psb)
If SUCCEEDED_(hr)
Protected.IShellView *psv
hr = *psb\QueryActiveShellView(@*psv)
If SUCCEEDED_(hr)
hr = *psv\QueryInterface(riid, @*ppv\i)
*psv\Release()
EndIf
*psb\Release()
EndIf
*pdisp\Release()
Else
hr = #E_FAIL
EndIf
*psw\Release()
EndIf
ProcedureReturn hr
EndProcedure
Procedure GetShellDispatchFromView(*psv.IShellView, riid, *ppv.Integer)
*ppv\i = 0
Protected.IDispatch *pdispBackground
#SVGIO_BACKGROUND = 0
Protected hr.l = *psv\GetItemObject(#SVGIO_BACKGROUND, @IID_IDispatch, @*pdispBackground)
If SUCCEEDED_(hr)
Protected.IShellFolderViewDual *psfvd
hr = *pdispBackground\QueryInterface(@IID_IShellFolderViewDual, @*psfvd)
If SUCCEEDED_(hr)
Protected.IDispatch *pdisp
hr = *psfvd\get_Application(@*pdisp)
If SUCCEEDED_(hr)
hr = *pdisp\QueryInterface(riid, @*ppv\i)
*pdisp\Release();
EndIf
*psfvd\Release()
EndIf
*pdispBackground\Release();
EndIf
ProcedureReturn hr
EndProcedure
Procedure ShellExecInExplorerProcess(sFile.s, sParameter.s = "")
Protected.IShellView *psv
Protected hr.l = GetShellViewForDesktop(@IID_IShellView, @*psv)
If SUCCEEDED_(hr)
Protected.IShellDispatch2 *psd
hr = GetShellDispatchFromView(*psv, @IID_IShellDispatch2, @*psd)
If SUCCEEDED_(hr)
Protected.VARIANT vArguments, vDirectory, vOperation, vShow
If sParameter <> ""
vArguments\vt = #VT_BSTR
vArguments\bstrVal = SysAllocString_(@sParameter)
EndIf
vShow\vt = #VT_I2
vShow\iVal = #SW_SHOWDEFAULT
hr = *psd\ShellExecute(sFile, @vArguments, @vDirectory, @vOperation, @vShow)
If vArguments\bstrVal
SysFreeString_(vArguments\bstrVal)
EndIf
*psd\Release()
EndIf
*psv\Release()
EndIf
ProcedureReturn hr
EndProcedure
Procedure WinMain()
Protected hr.l = CoInitializeEx_(#Null, #COINIT_APARTMENTTHREADED | #COINIT_DISABLE_OLE1DDE)
If SUCCEEDED_(hr)
ShellExecInExplorerProcess("notepad.exe", "C:\Windows\WindowsUpdate.log")
CoUninitialize_();
EndIf
ProcedureReturn 0;
EndProcedure
WinMain()
Re: Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 8:05 pm
by jacky
Holy cow
Quite a lot of code to do this with COM...
No clue how you did this, fryquez, but it's working perfectly fine.
Thanks so much!
Re: Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 9:49 pm
by BarryG
fryquez, what is your code meant to do? I assume it's to launch an admin exe as limited (because jacky said "Doesn't work, notepad will be elevated", so he wants Notepad to be limited?). If so, it doesn't work for me (I get a UAC prompt for any admin exe that I launch with it).
Re: Convert small .ahk (COM) to PB?
Posted: Wed Dec 30, 2020 9:58 pm
by jacky
The application that contains this code (and is started with "Run as administrator") can run another application with current user permissions. This should work for every user that is in the administrator group and is currently logged in but not necessarily for the user account "Administrator" itself.
Re: Convert small .ahk (COM) to PB?
Posted: Thu Dec 31, 2020 12:15 pm
by fryquez
I made small improvements to my previous post.
PS: The code is translated from
Windows-classic-samples
Re: Convert small .ahk (COM) to PB?
Posted: Thu Dec 31, 2020 2:43 pm
by BarryG
Hi jacky, I understand now. I can confirm it works as you describe (admin exe runs another exe as limited). Thanks to fryquez for the code!
Re: Convert small .ahk (COM) to PB?
Posted: Thu Dec 31, 2020 2:59 pm
by jacky
@fryquez
Thanks again!
I wanted to ask why sFile can be used directly without storing it in a variable of type VARIANT but after reading
https://docs.microsoft.com/en-us/window ... ellexecute
I'll understand it now
I've slightly modified your translated code (thanks for posting the link to the C++ source for it, incredible valuable!) by readding sWorkingDir and a mode argument so that a program can also be executed with a specific working directory and e.g. #SW_HIDE.
Code: Select all
Procedure ShellExecInExplorerProcess(sFile.s, sParameter.s = "", sWorkingDir.s = "", iMode = #SW_SHOWDEFAULT)
Protected.IShellView *psv
Protected hr.l = GetShellViewForDesktop(@IID_IShellView, @*psv)
If SUCCEEDED_(hr)
Protected.IShellDispatch2 *psd
hr = GetShellDispatchFromView(*psv, @IID_IShellDispatch2, @*psd)
If SUCCEEDED_(hr)
Protected.VARIANT vArguments, vDirectory, vOperation, vShow
If sParameter <> ""
vArguments\vt = #VT_BSTR
vArguments\bstrVal = SysAllocString_(@sParameter)
EndIf
vDirectory\vt = #VT_BSTR
If sWorkingDir = ""
vDirectory\bstrVal = SysAllocString_(GetPathPart(sFile))
Else
vDirectory\bstrVal = SysAllocString_(@sWorkingDir)
EndIf
vShow\vt = #VT_I2
vShow\iVal = iMode
hr = *psd\ShellExecute(sFile, @vArguments, @vDirectory, @vOperation, @vShow)
If vArguments\bstrVal
SysFreeString_(vArguments\bstrVal)
EndIf
If vDirectory\bstrVal
SysFreeString_(vDirectory\bstrVal)
EndIf
*psd\Release()
EndIf
*psv\Release()
EndIf
ProcedureReturn hr
EndProcedure
Re: Convert small .ahk (COM) to PB?
Posted: Thu Dec 31, 2020 3:28 pm
by BarryG
Jacky, I just modified your code to use the file's dir as the working dir if a working dir is NOT specified, because a working dir is sometimes needed for an app:
Code: Select all
vDirectory\vt = #VT_BSTR
If sWorkingDir = ""
vDirectory\bstrVal = SysAllocString_(GetPathPart(sFile))
Else
vDirectory\bstrVal = SysAllocString_(@sWorkingDir)
EndIf
Re: Convert small .ahk (COM) to PB?
Posted: Thu Dec 31, 2020 3:44 pm
by jacky
Yeah, that makes sense. I've added the change to my last post.