JoshAssing Posted November 13, 2008 Share Posted November 13, 2008 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 More sharing options...
Richard Robertson Posted November 13, 2008 Share Posted November 13, 2008 (edited) EndFunc ;==>JustPathFunc Replicate($cChar, $nTimes) Should be EndFunc ;==>JustPath Func Replicate($cChar, $nTimes) Edited November 13, 2008 by Richard Robertson Link to comment Share on other sites More sharing options...
trancexx Posted November 13, 2008 Share Posted November 13, 2008 #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 More sharing options...
PsaltyDS Posted November 13, 2008 Share Posted November 13, 2008 (edited) 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 Edit: Fixed boneheaded placement of DllClose(). Edited November 13, 2008 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 More sharing options...
PsaltyDS Posted November 13, 2008 Share Posted November 13, 2008 #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 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 More sharing options...
JoshAssing Posted November 13, 2008 Author Share Posted November 13, 2008 EndFunc ;==>JustPathFunc Replicate($cChar, $nTimes)Should beEndFunc ;==>JustPathFunc 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 More sharing options...
JoshAssing Posted November 13, 2008 Author Share Posted November 13, 2008 Even better!INDEED! THANK YOU! I was beating myself up on that... thank you for the lesson!-josh Link to comment Share on other sites More sharing options...
JoshAssing Posted November 13, 2008 Author Share Posted November 13, 2008 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 More sharing options...
PsaltyDS Posted November 13, 2008 Share Posted November 13, 2008 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-joshNo, 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. 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 More sharing options...
monoceres Posted November 13, 2008 Share Posted November 13, 2008 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 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-joshIt 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 More sharing options...
monoceres Posted November 13, 2008 Share Posted November 13, 2008 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. 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 More sharing options...
PsaltyDS Posted November 13, 2008 Share Posted November 13, 2008 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 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 More sharing options...
MrCreatoR Posted November 14, 2008 Share Posted November 14, 2008 _PathSplit not used there at all 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 Russian Community My Work... Spoiler Projects: 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 ProgramUDFs: 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 Examples: 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 ) * === My topics === * ================================================== ================================================== AutoIt is simple, subtle, elegant. © AutoIt Team Link to comment Share on other sites More sharing options...
trancexx Posted November 14, 2008 Share Posted November 14, 2008 (edited) 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? 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 November 14, 2008 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Richard Robertson Posted November 14, 2008 Share Posted November 14, 2008 You don't have to call DllOpen even if the dll isn't loaded by the executable. If you use a string name, it will open the library, make the call, then discard the library (if applicable). Link to comment Share on other sites More sharing options...
trancexx Posted November 14, 2008 Share Posted November 14, 2008 You don't have to call DllOpen even if the dll isn't loaded by the executable. If you use a string name, it will open the library, make the call, then discard the library (if applicable).You are running 3.4.15.12? ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Richard Robertson Posted November 14, 2008 Share Posted November 14, 2008 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 More sharing options...
trancexx Posted November 14, 2008 Share Posted November 14, 2008 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 More sharing options...
Richard Robertson Posted November 14, 2008 Share Posted November 14, 2008 So are you telling me that calling DllCall("myrandomdllthatautoithasntloaded.dll", ...) won't work? Link to comment Share on other sites More sharing options...
trancexx Posted November 15, 2008 Share Posted November 15, 2008 No, I'm not. I'm telling you that that code you wrote might not work because DllCall() is not working the way you described it. That is potentially "autoit3.exe has encountered a problem and needs to close..." situation. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now