Jump to content

AutoIT x64 problem


Recommended Posts

Hi!

I wrote an AutoIT which is supposed to get a hotkey from a .dll resource file and use it. It seems to run fine in an x86 environment, but i'm having problems in an x64 one.

This is the behavior I noticed: (always in an x86 environment)

1 - Running the script in x86 mode makes AutoIT crash.

2 - Running the script in x64 mode works fine.

3 - Compiling the script as an x64 executable and then running the executable makes AutoIT crash.

Here's the code:

#include <ResourceStrings.au3>

Global $ieframeDll = "C:\\Windows\\System32\\ieframe.dll"
Global $Ctrl = "^"
Global $Alt = "!"

OpenFileMenu()

Func OpenFileMenu()

Local $k = GetHotkeyFromResource($ieframeDll, 267, 32768)
ConsoleWriteLine($k)
Local $keys = $Alt & $k

Send($keys)

EndFunc

; Usage example:

;ConsoleWriteLine(GetHotkeyFromResource("C:\\Windows\\System32\\ieframe.dll", 334, 41025))

; ================= Main functions ====================

Func GetHotkeyFromResource($dllPath, $menuId, $stringId)

Local $string = GetStringFromResource($dllPath, $menuId, $stringId)
Local $charArray = StringSplit($string, "")

For $n = 1 To $charArray[0]
If $charArray[$n] = chr(38) Then
return $charArray[$n + 1]
EndIf
Next

EndFunc

Func GetStringFromResource($dllPath, $menuId, $stringId)

Local $ieframeHandle = LoadLibraryEx($dllPath)
Local $menuHandle = LoadMenu($ieframeHandle, $menuId)
Local $stringLength = GetMenuStringLength($menuHandle, $stringId)
return GetMenuString($menuHandle, $stringId, $stringLength)

EndFunc

; ================= kernel32.dll functions ====================

Func LoadLibraryEx($muiPath)

Local $result = DllCall("kernel32.dll", "ptr", "LoadLibraryEx", "str", $muiPath, "ptr", 0, "UINT", 0x2)
CheckDllCallError("LoadLibraryEx")
Return $result[0]

EndFunc

Func GetLastError()

Local $GetLastError = DllCall("kernel32.dll", "long", "GetLastError")
CheckDllCallError("GetLastError")
Return $GetLastError[0]

EndFunc ;==>_WinAPI_GetLastErrorEx

; ================= user32.dll functions ====================

Func LoadMenu($dllHandle, $menuID)

Local $result = DllCall("user32.dll", "ptr", "LoadMenu", "ptr", $dllHandle, "int", $menuID)
CheckDLLCallError("LoadMenu")
Return $result[0]

EndFunc

Func GetMenuStringLength($menuHandle, $itemID)

Local $result = DllCall("user32.dll", "int", "GetMenuString", "ptr", $menuHandle, "UINT", $itemID, "ptr", 0, "int", 0, "UINT", 0)
CheckDllCallError("GetMenuStringLength")
return $result[0]

EndFunc

Func GetMenuString($menuHandle, $itemID, $stringLength)

Local $str = "char msgArray[" & $stringLength & "]"
Local $dllStruct = DllStructCreate($str)

Local $msgBufferSize = DllStructGetSize($dllStruct)
Local $msgBufferPtr = DllStructGetPtr($dllStruct)

$result = DllCall("user32.dll", "int", "GetMenuString", "ptr", $menuHandle, "UINT", $itemID, "ptr", $msgBufferPtr, "int", $stringLength + 1, "UINT", 0)
CheckDllCallError("GetMenuString")
return DllStructGetData($dllStruct, 1)

EndFunc

; ================= Utils ====================

Func PrintLastError()

ConsoleWriteLine("LastError: " & Hex(GetLastError()))

EndFunc

Func ConsoleWriteLine($text)

ConsoleWrite($text & @CRLF)

EndFunc


Func ConsoleWriteIfNull($var, $message)

If not $var Then

ConsoleWriteLine($message)

EndIf

EndFunc

Func CheckDLLCallError($functionName)

Switch @error

Case 0
;ConsoleWriteLine("DLL call successful")
;GetLastError()
Case 1
ConsoleWriteLine("Status for " & $functionName & ": Unable to use the DLL file")
GetLastError()
Exit
Case 2
ConsoleWriteLine("Status for " & $functionName & ": Unknown return type")
GetLastError()
Exit
Case 3
ConsoleWriteLine("Status for " & $functionName & ": Function not found in the DLL file")
GetLastError()
Exit
Case 4
ConsoleWriteLine("Status for " & $functionName & ": Bad number of parameters")
GetLastError()
Exit
Case 5
ConsoleWriteLine("Status for " & $functionName & ": Bad parameter")
GetLastError()
Exit
Case Else

EndSwitch

EndFunc

Also, when combined with other code (which is very long therefore I will not post it unless required...), the script crashes even in x64 mode. I think that solving the above issue will probably enough to fix this one too.

Thanks in advance!

Link to comment
Share on other sites

  • Moderators

guillermoares, please don't bump your threads in less than 24 hours. That gives us all plenty of time to research your issue and try to assist :)

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

What EXACTLY do you mean by this part?

This is the behavior I noticed: (always in an x86 environment)

1 - Running the script in x86 mode makes AutoIT crash.

2 - Running the script in x64 mode works fine.

3 - Compiling the script as an x64 executable and then running the executable makes AutoIT crash.

Are you running this as an x64 executable in an x86 OS? Because that just won't ever work.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Ooops... No, I'm running my tests on an x64 environment. My bad.

Just to be sure... When I say "Running the script in x86/x64 mode[...]" I'm referring to the "Run script (x86)" and "Run script (x64)" options displayed when right-clicking on an AutoIT script.

Link to comment
Share on other sites

I can't duplicate the crash issues, I compiled as both an x64 and an x86 executable and both ran without a problem. I also ran it from SciTE in both modes and it worked there as well.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Hmmm... weird.

The exact environment is Windows 7 Ultimate SP1 x64 in spanish. Probably you are not testing on a spanish OS, but... is there any other difference between our environments?

Also, is it working fine? My code is supposed to get the hotkey regardless of the program/OS language. The example code I posted gets the hotkey for the "File" menu in Internet Explorer 9, so in an english version of IE you should get "F" and in a spanish version you should get "A" ("File" = "Archivo").

Link to comment
Share on other sites

Windows 7 x64 here, it gets the File menu regardless of which program is running. If I run the code from SciTE, it gets the File menu in SciTE, if I'm running the executable from Windows Explorer it opens the File menu in that program. Also, if I run either of the executables from the console in SciTE, it opens the file menu in Scite.

EDIT: English version of Windows BTW.

Edited by BrewManNH

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Found the solution!

I was having a buffer overrun when calling GetMenuString. Apparently it only caused trouble with some spanish string...

Here's the corrected code, for posterity:

; Usage example:

ConsoleWriteLine(GetHotkeyFromResource("C:\\Windows\\System32\\ieframe.dll", 334, 41025))

; ================= Main functions ====================

Func GetHotkeyFromResource($dllPath, $menuId, $stringId)

   Local $string = GetStringFromResource($dllPath, $menuId, $stringId)
   Local $charArray = StringSplit($string, "")

   For $n = 1 To $charArray[0]
   If $charArray[$n] = chr(38) Then
   return $charArray[$n + 1]
   EndIf
   Next

EndFunc

Func GetStringFromResource($dllPath, $menuId, $stringId)

   Local $ieframeHandle = LoadLibraryEx($dllPath)
   Local $menuHandle = LoadMenu($ieframeHandle, $menuId)
   Local $stringLength = GetMenuStringLength($menuHandle, $stringId)
   return GetMenuString($menuHandle, $stringId, $stringLength)

EndFunc

; ================= kernel32.dll functions ====================

Func LoadLibraryEx($muiPath)

   Local $result = DllCall("kernel32.dll", "ptr", "LoadLibraryEx", "str", $muiPath, "ptr", 0, "UINT", 0x2)
   CheckDllCallError("LoadLibraryEx")
   Return $result[0]

EndFunc

Func GetLastError()

   Local $GetLastError = DllCall("kernel32.dll", "long", "GetLastError")
   CheckDllCallError("GetLastError")
   Return $GetLastError[0]

EndFunc ;==>_WinAPI_GetLastErrorEx

; ================= user32.dll functions ====================

Func LoadMenu($dllHandle, $menuID)

   Local $result = DllCall("user32.dll", "ptr", "LoadMenu", "ptr", $dllHandle, "int", $menuID)
   CheckDLLCallError("LoadMenu")
   Return $result[0]

EndFunc

Func GetMenuStringLength($menuHandle, $itemID)

   Local $result = DllCall("user32.dll", "int", "GetMenuStringW", "ptr", $menuHandle, "UINT", $itemID, "ptr", 0, "int", 0, "UINT", 0)
   CheckDllCallError("GetMenuStringLength")
   return $result[0]

EndFunc

Func GetMenuString($menuHandle, $itemID, $stringLength)

   $result = DllCall("user32.dll", "int", "GetMenuStringW", "ptr", $menuHandle, "UINT", $itemID, "wstr", "", "int", 10000, "UINT", 0)
   return $result[3]

EndFunc

; ================= Utils ====================

Func PrintLastError()

   ConsoleWriteLine("LastError: " & Hex(GetLastError()))

EndFunc

Func ConsoleWriteLine($text)

   ConsoleWrite($text & @CRLF)

EndFunc


Func ConsoleWriteIfNull($var, $message)

   If not $var Then

   ConsoleWriteLine($message)

   EndIf

EndFunc

Func CheckDLLCallError($functionName)

   Switch @error

   Case 0
   ;ConsoleWriteLine("DLL call successful")
   ;GetLastError()
   Case 1
   ConsoleWriteLine("Status for " & $functionName & ": Unable to use the DLL file")
   GetLastError()
   Exit
   Case 2
   ConsoleWriteLine("Status for " & $functionName & ": Unknown return type")
   GetLastError()
   Exit
   Case 3
   ConsoleWriteLine("Status for " & $functionName & ": Function not found in the DLL file")
   GetLastError()
   Exit
   Case 4
   ConsoleWriteLine("Status for " & $functionName & ": Bad number of parameters")
   GetLastError()
   Exit
   Case 5
   ConsoleWriteLine("Status for " & $functionName & ": Bad parameter")
   GetLastError()
   Exit
   Case Else

   EndSwitch

Thanks again!

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...