Jump to content
Sign in to follow this  
RTFC

Execute(error macro)

Recommended Posts

RTFC

Greetings y'all,

While tracing an issue flagged by user MagicSpark here:

I came across this puzzling AutoIt behaviour:

Seterror(1)
If @error Then Beep(1111,100) ; this works

Seterror(1)
If Execute('@error') Then Beep(1111,100) ; this fails

Now I'm not sure whether this should be considered a bug or a feature. I presume Execute starts by resetting @error (and @extended) and updates it with a non-zero error code when something fails along the way. Trouble is, this makes evaluation of @error's origiinal content within an Execute envelope impossible, thereby breaking my decryption (see my CodeCrypter thread). The example above is of course just for illustration, but in Codecrypter any line containing @error no longer works (always returns zero for successful Execute).

In the absence of "onError' or some form of previous-error logging facilities, would it be possible to preserve the state of @error and @extended (for example, through internal tempvars) inside the Execute handling itself just sufficiently long for actual evaluation to be possible?

I realise this is a bit of a chicken-and-egg situation, but before I code up an elaborate work-around in CodeCrypter, I'd like to check with you devs whether a simple fix would resolve this.

Thanks for looking into this,

RT

  • Like 1

Share this post


Link to post
Share on other sites
jchd

I don't consider this as a workaround, rather correct use of Execute:

Seterror(1)
If @error Then MsgBox(0, "", "If") ; this works

Seterror(1)
If Execute('@error = 0') Then MsgBox(0, "", "Execute") ; this works as well

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites
RTFC

Thanks for your response, but you're testing the wrong condition. As I wrote, @error always comes back zero inside an Execute, whereas I'm testing non-zero. As far as I can tell, your example still fails, like this:

Seterror(1)
If @error Then Beep(1111,100)   ; this works

Seterror(1)
If Execute('@error=1') Then Beep(2222,100)  ; this fails

Share this post


Link to post
Share on other sites
jchd

Oops, that's a good hint that I need some sleep. You're of course right on this point.


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites
czardas

This might give you some ideas. The code is a bit ugly, but the concept is straight forward enough. I still haven't got around to using this method with the project I had originally intended, which also uses Execute BTW.

Edited by czardas

Share this post


Link to post
Share on other sites
RTFC

Hi czardas,

That's a great collection of snippets you 've got there (hadn't seen these before). :) BTW love your music-related contributions to the forums!

I understand the idea you suggest, but I'm afraid in this particular case it won't solve the problem. The user is testing the contents of @error directly after calling some AutoIt function (or maybe setting @error directly with SetError(1), as in my little example). But since the code that evaluates the content of @error is wrapped inside an Execute envelope, it is reset to zero (by Execute itself) prior to its evaluation wthin the Execute execution :wacko: (sounds confusing, doesn't it?). In the CodeCrypter thread I referred to in the original post, I suggested the workaround to insert an extra line of unencrypted code into the fully encrypted script afterwards that would capture the @error status in a regular $variable that can subsequently be evaluated at leisure (as it won't be wiped by an Execute call). But one would have to do this manually at all locations where @error is checked, and repeat all edits whenever one generates a new version of the encrypted script. So that's not an option.

As I understand it, the problem lies inside the Execute command itself, and the question boils down to whether @error's status as determined by executing the previous line can somehow be preserved just long enough inside the Execute command handler to enable evaluation of that status.

So instead of this:

1. some call sets @error nonzero
2. some statement with Execute('@error')
   a) reset @error, @extended
   b) check for errors, set @error if any test fails
   c) parse string to internal AutoIt command processor

I'd imagine something like this:

1. some call sets @error nonzero
2. some statement with Execute('@error')
   a) local $error=@error
   b) local $extended=@extended
   c) reset @error, @extended
   d) check for errors, set @error if any test fails
   e) replace @error with $error, @extended with $extended in the parameter string
   f) parse string to internal AutoIt command processor

Perhaps this would be easy to fix, or perhaps not; I can't tell. :(  But in the absence of 'OnError' constructs I cannot think of any way that this could be fixed at the script level. Any subsequent code the user produces to avoid this is itself also Execute-wrapped in CodeCrypter, so the reset still occurs before the original status can be captured. :think:

Share this post


Link to post
Share on other sites
czardas

I see. It is indeed complex. I have 50+ maths functions, either ones I modified or ones wrote myself, which (when tested) ought to nest and still support error handling; but there is no encryption involved. Modifying 50 functions is enough for my purposes, but if I had to do more then I would probably start to look for other solutions.

Thanks for your comments. The snippet dump has some rubbish in there too. I try to clean the thread up every now and again. :whisper:

Edited by czardas

Share this post


Link to post
Share on other sites
Richard Robertson

I'm pretty sure most of the AutoIt built in functions reset the error code when they start as boilerplate code.

Share this post


Link to post
Share on other sites
RTFC

Hi Richard Robertson,

Yeah, that's what I feared. :( So my questions are,

1) given the special "meta" nature of the Execute command, and (as I understand it at least) that it is supposed to parse its argument as-is to AutoIt's internal command handler as an executable AutoIt phrase, does the fact that it itself alters the state of @error prior to parsing it constitute a bug in the way the Execute command handles @error?

2) if so, could this be easily patched in a future release? That is, does @error get reset by a generic preprocessor that then passes control to specific command handlers or does each command handler do this internally (so it would be easier to handle Execute's special case scenario)?

I guess only a core dev would be able to answer that...

I'd really like to know one way or the other, because if it cannot/won't be fixed then I'll have to design an elaborate work-around that I'd rather avoid for various reasons (not just being lazy).

Anyway, thanks for your input.

Share this post


Link to post
Share on other sites
Richard Robertson

From the help file on the page "Function Notes"

@error is always set to 0 when entering in a function.

 

This is intended behavior and not a bug. It also appears that every built in function resets the error state.

  • Like 1

Share this post


Link to post
Share on other sites
RTFC

Much obliged, Richard, I missed that note completely.

In that case, I will write a work-around for CodeCrypter.

Thanks for clearing that up, I'll mark this thread as resolved.

RT

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  

  • Similar Content

    • Kaarl
      By Kaarl
      Hi,
      I have this piece code that works with Excel file and finds the column name where is a specific named range located.
      Local $Column = Null $Column = _Excel_ColumnToLetter($oWorkbook.Sheets("MySheetName").Range("MyRangeName").Column) If @error Then $Column = Null SetError(0) Else ;Proceed... EndIf It works properly if the named range exists in the Excel file, I do get the column name and the "Proceed" part is correctly executed. If the named range is not present in the Excel file, I would expect the If @error part to set the variable to Null and then follow with the rest of the function after EndIf. Instead, the script stops and I get this error:
      "C:\test\script_021.au3" (1184) : ==> The requested action with this object has failed.: $Column = _Excel_ColumnToLetter($oWorkbook.Sheets("MySheetName").Range("MyRangeName").Column) $Column = _Excel_ColumnToLetter($oWorkbook.Sheets("MySheetName")^ ERROR What am I doing wrong here? Is it possible that failure to set the variable doesn't set the @error? Push in the right direction would be much appreciated. Thanks!
    • rkr
      By rkr
      Hi, I have a software which has a 'run file'-ie; when i double click on that file, the input file of the software is run by the software. I wish to double click/execute this run file using autoit. how do i achieve this. i opened the software and it shows the input file and run file in same folder, i will put my autoitscript file too in same location. how do i simulate double clicking the run file (using its file name, say - abc.run ). I entered the following lines to make software window active - it became active, dont know how to go forward
      Winactivate("program title")
      winwaitactivate("program title")
      controlclick("program title","abc.run",1000,"primary",2) ; 1000 is ctrl id
    • SchneiMi
      By SchneiMi
      Hello,
      following my previous question, I have moved all potentially instable object interactions into Executes. But it Looks like "="-assignments to object Attributes cannot be done with Execute, only method calls. Using an "$obj = 1" construct, it compares (Eval) instead of sets (Execute) the value.
      I have tested multiple different combinations, using Execute and Assign, but it seems not to work with object Attributes. :-(
      Gives following Output:
      The assign Action using apply (a3) Fails, while assigning it directly, without Assign() works fine.
      The execute versions compare and do not assign, in both cases. Though, the "Execute" topic in the help file says it executes, not evaluates.
      I have found a similar, old thread, which explains this behavious but does not give a solution. https://www.autoitscript.com/forum/topic/110228-pass-object-property-as-a-variable/  
      Is there a way to assign to a com object's Attribute? Or is there anything new to this unexpected behaviour of Execute (at least compared to the help file description and Python's exec).
       
      Any help is appreciated, and thank you for all the help so far.
      Regards, Michael
       
    • RC86
      By RC86
      Hi all,
      Bit of a fun one with querying WMI objects and setting errors within a function.  Below is example code that I've used from JSThePatriot previous UDFs but the example would apply to many other scenarios.  Basically the SetError should be called if $colItems is not an object as a result of the WMI query.  This is then used to create a corresponding error message.
      I've tried disabling WMIC thus forcing it to not be an object, but rather than catching the error and telling me about it, the code simply fails therefore surely making the purpose of the logging useless??  I've experienced this before but in other languages such as java i would use a try catch etc and get around this....any suggestions for its use in AutoIT?

      Thanks
       
       
      #region Header #comments-start Title: Computer Information Automation UDF Library for AutoIt3 - EXAMPLES Filename: CompInfoExamples.au3 Description: Examples using the UDF's from CompInfo.au3 Author: Jarvis J. Stubblefield (JSThePatriot) http://www.vortexrevolutions.com/ Version: 00.03.08 Last Update: 11.09.06 Requirements: AutoIt v3.2 +, Developed/Tested on WindowsXP Pro Service Pack 2 Notes: Errors associated with incorrect objects will be common user errors. AutoIt beta 3.1.1.63 has added an ObjName() function that will be used to trap and report most of these errors. Special thanks to Firestorm (Testing, Use), Koala (Testing, Bug Fix), and everyone else that has helped in the creation of this Example File. #comments-end #endregion Header #region Global Variables and Constants If Not(IsDeclared("$cI_CompName")) Then Global $cI_CompName = @ComputerName EndIf Global Const $cI_VersionInfo = "00.03.08" Global Const $cI_aName = 0, _ $cI_aDesc = 4 Global $wbemFlagReturnImmediately = 0x10, _ ;DO NOT CHANGE $wbemFlagForwardOnly = 0x20 ;DO NOT CHANGE Global $ERR_NO_INFO = "Array contains no information", _ $ERR_NOT_OBJ = "$colItems isnt an object" #endregion Global Variables and Constants #Region Boot Configuration Dim $BootConfig _ComputerGetBootConfig($BootConfig) If @error Then $error = @error $extended = @extended Switch $extended Case 1 _ErrorMsg($ERR_NO_INFO) Case 2 _ErrorMsg($ERR_NOT_OBJ) EndSwitch EndIf For $i = 1 To $BootConfig[0][0] Step 1 MsgBox(0, "Test _ComputerGetBootConfig", "Name: " & $BootConfig[$i][0] & @CRLF & _ "Boot Directory: " & $BootConfig[$i][1] & @CRLF & _ "Configuration Path: " & $BootConfig[$i][2] & @CRLF & _ "Last Drive: " & $BootConfig[$i][3] & @CRLF & _ "Description: " & $BootConfig[$i][4] & @CRLF & _ "Scratch Directory: " & $BootConfig[$i][5] & @CRLF & _ "Setting ID: " & $BootConfig[$i][6] & @CRLF & _ "Temp Directory: " & $BootConfig[$i][7]) Next #endregion Boot Configuration #region ---- Internal Functions Func _ErrorMsg($message, $time = 0) MsgBox(48 + 262144, "Error!", $message, $time) ConsoleWrite("Error!" & $message & $time & @CRLF) EndFunc #endregion Internal Functions Func _ComputerGetBootConfig(ByRef $aBootConfigInfo) Local $colItems, $objWMIService, $objItem Dim $aBootConfigInfo[1][8], $i = 1 $objWMIService = ObjGet("winmgmts:\\" & $cI_Compname & "\root\CIMV2") $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BootConfiguration", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly) If IsObj($colItems) Then For $objItem In $colItems ReDim $aBootConfigInfo[UBound($aBootConfigInfo) + 1][8] $aBootConfigInfo[$i][0] = $objItem.Name $aBootConfigInfo[$i][1] = $objItem.BootDirectory $aBootConfigInfo[$i][2] = $objItem.ConfigurationPath $aBootConfigInfo[$i][3] = $objItem.LastDrive $aBootConfigInfo[$i][4] = $objItem.Description $aBootConfigInfo[$i][5] = $objItem.ScratchDirectory $aBootConfigInfo[$i][6] = $objItem.SettingID $aBootConfigInfo[$i][7] = $objItem.TempDirectory $i += 1 Next $aBootConfigInfo[0][0] = UBound($aBootConfigInfo) - 1 If $aBootConfigInfo[0][0] < 1 Then SetError(1, 1, 0) EndIf Else SetError(1, 2, 0) EndIf EndFunc ;_ComputerGetBootConfig  
    • TheDcoder
      By TheDcoder
      Hello, I recently opened a bug report without reading the Helpfile... My bad . After @Melba23's gentle reminder, I was curious about why it was like that.
      It is about SetError's behaviour. This is the example from the bug report:
      Example() If @error Then ConsoleWrite("Error" & @CRLF) Else ConsoleWrite("No Error" & @CRLF) EndIf Func Example() SetError(1) Sleep(1000) EndFunc What I tried to do is set Example's (my user defined function's) @error value to 1... but the value set by SetError is cleared after calling a function, I wonder why? Why should calling to an external function effect my function's @error which is set when my function returns.
      Setting the error of a UDF in advance by using SetError makes sense... but I cannot find a reason why calling a function should clear it? Please note that I am not talking about @error, I am talking about the @error set by my function when it ends/returns!
      I hope someone can enlighten me, thanks for the answers in advance!
      P.S I tried to explain my best but my English is not very good and I didn't feel like I did a good job explaining today, so please pardon any mistakes that I have made
×