Sign in to follow this  
Followers 0
water

Grab runtime errors when script is run from a service

10 posts in this topic

I'm sure I can't find the obvious. Could anyone be so kind and point me into the right direction?

I have a quite complex user provisioning script which is started by a software running as a service on a dedicated server.

I had a bug in my script causing message "Error: Array variable has incorrect number of subscripts or subscript dimension range exceeded."

The msgbox with the error message couldn't be displayed to the console so it took me some time to find the error.

I compiled the script as CUI but still get the MsgBox.

My question: Is there a way to let AutoIt not display a MsgBox but write such error messages to a file or the eventlog or whatever?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites



I am also waiting for this solution.

rgds

deltarocked.

Share this post


Link to post
Share on other sites

Anyone?

Or is this something for a feature request?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Hook into MessageBox procedure.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
If @Compiled Then _AddHookApi("user32.dll", "MessageBoxW", "_Intercept_MessageBoxW", "int", "hwnd;wstr;wstr;uint")
Func _Intercept_MessageBoxW($hWnd, $sText, $sTitle, $iType)
If $sTitle = "AutoIt Error" Then
     ; For example:
     ConsoleWriteError($sTitle & " " & $sText & @CRLF)
Else
     Local $aCall = DllCall("user32.dll", "int", "MessageBoxW", _
             "hwnd", $hWnd, _
             "wstr", $sText, _
             "wstr", $sTitle, _
             "uint", $iType)
     If @error Or Not $aCall[0] Then Return 0
     Return $aCall[0]
EndIf
EndFunc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Let's try it (don't forget to compile)
; Usual message box
MsgBox(0, 'Test', 'Some text')
; Cause array error
Global $aArray[3] = [1, 2, 3]
$aArray[4] = 4 ; !!!!



Func _AddHookApi($sModuleName, $vFunctionName, $vNewFunction, $sRet = "", $sParams = "")
Local Static $pImportDirectory, $hInstance
If Not $pImportDirectory Then
     $hInstance = _GetModuleHandle()
     If @error Then Return SetError(1, 0, 0)
     Local $aCall = DllCall("dbghelp.dll", "ptr", "ImageDirectoryEntryToData", _
             "handle", $hInstance, _
             "boolean", 1, _ ; as an image
             "word", 1, _ ; IMAGE_DIRECTORY_ENTRY_IMPORT
             "dword*", 0)
     If @error Or Not $aCall[0] Then Return SetError(2, 0, 0)
     $pImportDirectory = $aCall[0]
EndIf
Local $iIsInt = IsInt($vFunctionName)
Local $iRestore = Not IsString($vNewFunction)
Local $tIMAGE_IMPORT_MODULE_DIRECTORY
Local $pDirectoryOffset = $pImportDirectory
Local $tModuleName
Local $iInitialOffset, $iInitialOffset2
Local $iOffset2
Local $tBufferOffset2, $iBufferOffset2
Local $tBuffer, $tFunctionOffset, $pOld, $fMatch
Local Const $PAGE_READWRITE = 0x04
While 1
     $tIMAGE_IMPORT_MODULE_DIRECTORY = DllStructCreate("dword RVAOriginalFirstThunk;" & _
             "dword TimeDateStamp;" & _
             "dword ForwarderChain;" & _
             "dword RVAModuleName;" & _
             "dword RVAFirstThunk", _
             $pDirectoryOffset)
     If Not DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") Then ExitLoop
     $tModuleName = DllStructCreate("char Name[64]", $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAModuleName"))
     If DllStructGetData($tModuleName, "Name") = $sModuleName Then ; function from this module
         $iInitialOffset = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk")
         $iInitialOffset2 = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAOriginalFirstThunk")
         If $iInitialOffset2 = $hInstance Then $iInitialOffset2 = $iInitialOffset
         $iOffset2 = 0
         While 1
             $tBufferOffset2 = DllStructCreate("dword_ptr", $iInitialOffset2 + $iOffset2)
             $iBufferOffset2 = DllStructGetData($tBufferOffset2, 1)
             If Not $iBufferOffset2 Then ExitLoop
             If $iIsInt Then
                 If BitAND($iBufferOffset2, 0xFFFFFF) = $vFunctionName Then $fMatch = True; wanted function
             Else
                 $tBuffer = DllStructCreate("ushort Ordinal; char Name[64]", $hInstance + $iBufferOffset2)
                 If DllStructGetData($tBuffer, "Name") == $vFunctionName Then $fMatch = True; wanted function
             EndIf
             If $fMatch Then
                 $tFunctionOffset = DllStructCreate("ptr", $iInitialOffset + $iOffset2)
                 _VirtualProtect(DllStructGetPtr($tFunctionOffset), DllStructGetSize($tFunctionOffset), $PAGE_READWRITE)
                 If @error Then Return SetError(3, 0, 0)
                 $pOld = DllStructGetData($tFunctionOffset, 1)
                 If $iRestore Then
                     DllStructSetData($tFunctionOffset, 1, $vNewFunction)
                 Else
                     DllStructSetData($tFunctionOffset, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction, $sRet, $sParams)))
                 EndIf
                 Return $pOld
             EndIf
             $iOffset2 += DllStructGetSize($tBufferOffset2)
         WEnd
         ExitLoop
     EndIf
     $pDirectoryOffset += 20 ; size of $tIMAGE_IMPORT_MODULE_DIRECTORY
WEnd
Return SetError(4, 0, 0)
EndFunc

Func _VirtualProtect($pAddress, $iSize, $iProtection)
Local $aCall = DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $pAddress, "dword_ptr", $iSize, "dword", $iProtection, "dword*", 0)
If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
Return 1
EndFunc

Func _GetModuleHandle($vModule = 0)
Local $sParamType = "ptr"
If IsString($vModule) Then $sParamType = "wstr"
Local $aCall = DllCall("kernel32.dll", "ptr", "GetModuleHandleW", $sParamType, $vModule)
If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
Return $aCall[0]
EndFunc
Edited by trancexx
1 person likes this

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Wow! Thanks a lot for this code!

Will test as soon as possible!

Do you think it makes sense to post a feature request?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Well, I'll just say that using message box to display error in console app is questionable choice.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

How many lines does your script has? If not too much I would check all array operation and put a console debug to cui with information.

How you do compile your script (which parameters)?

You can use

#AutoIt3Wrapper_Run_Obfuscator=y
#Obfuscator_Parameters=/so

and check out the <filename>_Obfuscated.au3. The line number should be somewhere near line which is displayed in message box.

Here an example:

#AutoIt3Wrapper_Run_Obfuscator=y
#Obfuscator_Parameters=/so

#include <Array.au3>

Global $a[1], $i = 1

$i += 1

$a[$i] = 1

_ArrayDisplay($a)

MsgBox(0, "Test", $a[$i])

If you compile an run it it will produce an em. For me at line 198. If I open now the <filename>_Obfuscated.au3 and jump to 198 and there it is.

On another example the line was 20 lines below. Probably I've to remove the _ line breaks...

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

I just saw small but fatal error in my code. Corrected.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Thanks trancexx!

I just tested on Windows 7 SP1 64 bit and Windows 2008 R2 server SP1 64 bit and it works great!


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
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
Sign in to follow this  
Followers 0