Jump to content

Calling FindExecutable API


Recommended Posts

I tried to wrap FindExecutable() API into a function call - but it doesn't seem to work; any suggestions?

Func FindExecutable($cFile)
    Local $hndDLL = DllOpen("shell32.dll")
    Local $cPath = JustPath($cFile)
    Local $cEXE = Replicate(" ", 250)
    Local $ptrResult = DllCall($hndDLL, "int", "FindExecutableA", "str", $cFile, "str", $cPath, "str", $cEXE)
    MsgBox(0, $cFile, @error)
    MsgBox(0, $cFile, $cPath)
    MsgBox(0, $cFile, $cEXE)
    DllClose($hndDLL)
    Return $cEXE
EndFunc  ;==>FindExecutable

Func JustPath($cPath)
    Local $szDrive, $szDir, $szFName, $szExt
    _PathSplit($cPath, $szDrive, $szDir, $szFName, $szExt)
    Return $szDrive & $szDir
EndFunc  ;==>JustPathFunc Replicate($cChar, $nTimes)
    Local $x
    Local $cReturn = ""
    For $x = 1 To $nTimes
        $cReturn = $cReturn & $cChar
    Next
    Return $cReturn
EndFunc  ;==>Replicate
Link to comment
Share on other sites

#include <File.au3>

Func FindExecutable($cFile)
    Local $hndDLL = DllOpen("shell32.dll")
    Local $cPath = JustPath($cFile)    
    Local $cEXE = DllStructCreate("char[260]")
    Local $ptrResult = DllCall($hndDLL, "int", "FindExecutableA", "str", $cFile, "str", $cPath, "ptr", DllStructGetPtr($cEXE))
    MsgBox(0, $cFile, @error)
    MsgBox(0, $cFile, $cPath)
    MsgBox(0, $cFile, DllStructGetData($cEXE, 1))
    DllClose($hndDLL)
    Return $cEXE
EndFunc  ;==>FindExecutable

Func JustPath($cPath)
    Local $szDrive, $szDir, $szFName, $szExt
    _PathSplit($cPath, $szDrive, $szDir, $szFName, $szExt)
    Return $szDrive & $szDir
EndFunc  ;==>JustPath

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I tried to wrap FindExecutable() API into a function call - but it doesn't seem to work; any suggestions?

Func FindExecutable($cFile)
    Local $hndDLL = DllOpen("shell32.dll")
    Local $cPath = JustPath($cFile)
    Local $cEXE = Replicate(" ", 250)
    Local $ptrResult = DllCall($hndDLL, "int", "FindExecutableA", "str", $cFile, "str", $cPath, "str", $cEXE)
    MsgBox(0, $cFile, @error)
    MsgBox(0, $cFile, $cPath)
    MsgBox(0, $cFile, $cEXE)
    DllClose($hndDLL)
    Return $cEXE
EndFunc;==>FindExecutable

Func JustPath($cPath)
    Local $szDrive, $szDir, $szFName, $szExt
    _PathSplit($cPath, $szDrive, $szDir, $szFName, $szExt)
    Return $szDrive & $szDir
EndFunc;==>JustPathFunc Replicate($cChar, $nTimes)
    Local $x
    Local $cReturn = ""
    For $x = 1 To $nTimes
        $cReturn = $cReturn & $cChar
    Next
    Return $cReturn
EndFunc;==>Replicate
I got this to work:
#include <Array.au3>

Global $sFile = "AutoIt3.chm"
Global $sPath = "C:\Program Files\AutoIt3"
Global $Return = FindExecutable($sFile, $sPath)
Global $iErrSav = @error
Global $iExtSav = @extended
If @error Then
    MsgBox(16, "Error", "Error retrieving executable for:" & @CRLF & _
            $sPath & "\" & $sFile & @CRLF & _
            "@error = " & $iErrSav & "  @extended = " & $iExtSav & @CRLF & _
            "$Return = " & $Return)
Else
    _ArrayDisplay($Return, "Success: $Return")
EndIf


Func FindExecutable($sFileIn, $sPathIn)
    Local $sEXE; Not used?
    Local $RET; Return from DLL
    Local $hDLL = DllOpen("shell32.dll")
    $RET = DllCall($hDLL, "int", "FindExecutableA", "str", $sFileIn, "str", $sPathIn, "str", $sEXE)
    DllClose($hDLL)
    If IsArray($RET) Then
        Return $RET
    Else
        Return SetError(1, $RET, 0)
    EndIf
EndFunc ;==>FindExecutable

:mellow:

Edit: Fixed boneheaded placement of DllClose().

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

#include <File.au3>

Func FindExecutable($cFile)
    Local $hndDLL = DllOpen("shell32.dll")
    Local $cPath = JustPath($cFile) 
    Local $cEXE = DllStructCreate("char[260]")
    Local $ptrResult = DllCall($hndDLL, "int", "FindExecutableA", "str", $cFile, "str", $cPath, "ptr", DllStructGetPtr($cEXE))
    MsgBox(0, $cFile, @error)
    MsgBox(0, $cFile, $cPath)
    MsgBox(0, $cFile, DllStructGetData($cEXE, 1))
    DllClose($hndDLL)
    Return $cEXE
EndFunc ;==>FindExecutable

Func JustPath($cPath)
    Local $szDrive, $szDir, $szFName, $szExt
    _PathSplit($cPath, $szDrive, $szDir, $szFName, $szExt)
    Return $szDrive & $szDir
EndFunc ;==>JustPath
Even better!

#include <File.au3>

$sFile = "C:\Program Files\AutoIt3\AutoIt3.chm"
$sExecutable = FindExecutable($sFile)
ConsoleWrite("$sExecutable = " & $sExecutable & @LF)

Func FindExecutable($cFile)
    Local $hDLL = DllOpen("shell32.dll"), $cPath, $cFDrive, $cFDir, $cFName, $cFExt
    _PathSplit($cPath, $cFDrive, $cFDir, $cFName, $cFExt)
    Local $structEXE = DllStructCreate("char[260]")
    Local $avResult = DllCall($hDLL, "int", "FindExecutableA", "str", $cFile, "str", $cPath, "ptr", DllStructGetPtr($structEXE))
    DllClose($hDLL)
    Return SetError(@error, 0, DllStructGetData($structEXE, 1))
EndFunc ;==>FindExecutable

:mellow:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

EndFunc ;==>JustPathFunc Replicate($cChar, $nTimes)

Should be

EndFunc ;==>JustPath

Func Replicate($cChar, $nTimes)

Thanks -- that was purely a copy/paste issue... I had to copy the replicate & justpath functions when I noticed that the code "as is" wouldn't run....

the code in the .au3 file is correct.

Link to comment
Share on other sites

Func FindExecutable($sFileIn, $sPathIn)

Local $sEXE; Not used?

Local $RET; Return from DLL

Local $hDLL = DllOpen("shell32.dll")

$RET = DllCall($hDLL, "int", "FindExecutableA", "str", $sFileIn, "str", $sPathIn, "str", $sEXE)

If IsArray($RET) Then

Return $RET

Else

Return SetError(1, $RET, 0)

EndIf

DllClose($hDLL)

EndFunc ;==>FindExecutable

Interesting -- so AutoIT continues processing a function code even after a return is issued? I would have thought the dllclose needed to go before a return.

Reading the API doc; the $sEXE should hold the information; and the dll's return is an integer; so how does $RET get filled as an array?

Thanks

-josh

Link to comment
Share on other sites

Interesting -- so AutoIT continues processing a function code even after a return is issued? I would have thought the dllclose needed to go before a return.

Reading the API doc; the $sEXE should hold the information; and the dll's return is an integer; so how does $RET get filled as an array?

Thanks

-josh

No, that was a boneheaded mistake on my part.

DLLClose() is proper clean up, but not critical though. AutoIt closes all open handles on exit. Unless you called it in a recursive loop or something you probably wouldn't notice the difference.

:mellow:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Interesting -- so AutoIT continues processing a function code even after a return is issued? I would have thought the dllclose needed to go before a return.

And you are right. What we have here is a classical memory leak. That's a bad penguin, bad :mellow:

Reading the API doc; the $sEXE should hold the information; and the dll's return is an integer; so how does $RET get filled as an array?

Thanks

-josh

It does but AutoIt returns the data from the dll as an array.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

No, that was a boneheaded mistake on my part.

DLLClose() is proper clean up, but not critical though. AutoIt closes all open handles on exit. Unless you called it in a recursive loop or something you probably wouldn't notice the difference.

:mellow:

Actually that was what I thought, until testing. It appears that it does not get unloaded when the variable is destroyed.

Watch the mem usage:

While True
    bla()
WEnd


Func bla()
    $temp=DllOpen("Kernel32.dll")
EndFunc

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Actually that was what I thought, until testing. It appears that it does not get unloaded when the variable is destroyed.

Watch the mem usage:

While True
    bla()
WEnd

Func bla()
    $temp=DllOpen("Kernel32.dll")
EndFunc
I meant all handles are closed at script Exit, not function return. But handles created inside the function should certainly be closed by the function.

Emperor penguin should not forget the foreign users :mellow:

instead of $sFile = "C:\Program Files\AutoIt3\AutoIt3.chm"

use macro $sFile = @ProgramFilesDir&"\AutoIt3\AutoIt3.chm"

Penguins never forget, they remember at a time of their own choosing:
$sFile = RegRead("HKLM\SOFTWARE\AutoIt v3\AutoIt", "InstallDir") & "\AutoIt3.chm"

:(

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

_PathSplit not used there at all :mellow:

It should be like this (no _PathSplit):

$sFile = "C:\Boot.ini"
$sExecutable = _FileFindExecutable($sFile)
ConsoleWrite("$sExecutable = " & $sExecutable & @LF)

Func _FileFindExecutable($sFile)
    Local $hDLL = DllOpen("shell32.dll")
    Local $sPath = StringRegExpReplace($sFile, "\\[^\\]*$", "")
    
    Local $structEXE = DllStructCreate("char[260]")
    DllCall($hDLL, "int", "FindExecutableA", "str", $sFile, "str", $sPath, "ptr", DllStructGetPtr($structEXE))
    
    DllClose($hDLL)
    
    Return SetError(@error, 0, DllStructGetData($structEXE, 1))
EndFunc ;==>_FileFindExecutable

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

If one would divide AutoIt's relationship with dlls found on system in circles (9 of hell, khm... khm...), the closest one, circle that is, would contain:

-advapi32.dll

-comctl32.dll

-comdlg32.dll

-gdi32.dll

-kernel32.dll

-mpr.dll

-ole32.dll

-oleaut32.dll

-shell32.dll

-user32.dll

-version.dll

-winmm.dll

-wsock32.dll

Next one would have this dlls inside:

-imm32.dll

-msctf.dll

-msvcrt.dll

-ntdll.dll

-rpcrt4.dll

-secur32.dll

-setupapi.dll

-shlwapi.dll

-uxtheme.dll

-ws2help.dll

-ws2_32.dll

Third circle would add some more, etc...

Why me writing this? :mellow:

Because calling functions from dlls found in first three circles does not require DllOpen().

$sFile = "C:\Boot.ini"
$sExecutable = _FileFindExecutable($sFile)
If Not @error Then
    ConsoleWrite("$sExecutable = " & $sExecutable & @CRLF)
Else
    If @error = 1 Then
        MsgBox(48, "Error", "DllCall() failed")
    Else
        If @extended = 2 Then
            MsgBox(48, "Error", "The specified file was not found.")
        ElseIf @extended = 31 Then
            MsgBox(48, "Error", "There is no association for the specified file type.")
        ElseIf @extended = 8 Then
            MsgBox(48, "Error", "The system is out of memory or resources.")
        Else
            MsgBox(48, "Error", "Unknown error occurred.") ; should not happen!
        EndIf
    EndIf
EndIf

Func _FileFindExecutable($sFile)

    Local $structEXE = DllStructCreate("char[260]")
    Local $a_iCall = DllCall("shell32.dll", "int", "FindExecutable", "str", $sFile, "str", "", "ptr", DllStructGetPtr($structEXE))
    
    If @error Then
        Return SetError(1, 0, "")
    EndIf
    
    If $a_iCall[0] < 32 Then
        Return SetError(2, $a_iCall[0], "")
    EndIf
    
    Return SetError(0, 0, DllStructGetData($structEXE, 1))

EndFunc   ;==>_FileFindExecutable
Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

It doesn't matter what version. DllCall is meant to take either a handle or a string name. If you give it a string, it will attempt to load the dll, find the function, and call it. Once that is done, it will close the dll. If you pass it a handle however, it will just search the given handle for the function, then try to call it.

Link to comment
Share on other sites

It doesn't matter what version. DllCall is meant to take either a handle or a string name. If you give it a string, it will attempt to load the dll, find the function, and call it. Once that is done, it will close the dll. If you pass it a handle however, it will just search the given handle for the function, then try to call it.

No, it doesn't work that way.

I've just checked the help file and it's basically saying the same thing. That is wrong.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...