Jump to content
ModemJunki

Help with compiler from within a script - bug in ShellExecuteWait?

Recommended Posts

ModemJunki

Hello,

I have an issue with compiling a file from inside a script using 3.3.14.5.

The script is kind of long so I will try to paraphrase what is happening.

First, I get the compiler locations and store them in variables:

Global $compileExe86 = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Aut2Exe.exe", "")
Global $compileExe64 = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Aut2Exe_x64.exe", "")

Then later I parse an array within a function to compile a list of files one at a time. The function accepts "x86" for files to be compiles as x86 and "x64" for 64-bit compiling.

If $s_arch = "x86" Then
                $s_action = "/in " & @ScriptDir & "\" & $a_CompileFiles[$i][0] & " /out " & @ScriptDir & "\" & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe") & " /pack /comp 4 /icon " & $icon ; x86
            ElseIf $s_arch = "x64" Then
                $s_action = "/in " & @ScriptDir & "\" & $a_CompileFiles[$i][0] & " /out " & @ScriptDir & "\" & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe") & " /pack /comp 4 /icon " & $icon & " /x64" ; x64
            EndIf
            
$s_err = ShellExecuteWait($compileExe, $s_action, @ScriptDir, $SHEX_OPEN, @SW_HIDE)

The problem is that $s_err will return 0 if the file is compiled successfully or not - for example, if one of the files uses FileInstall() but the file to be installed is not present, I still get a return of 0, but if I compile the same file from the command line I get a return of 3 as the errorlevel.

This happens even though Aut2Exe is popping up an error dialog that has to be confirmed.

I also tried with RunWait and got the same result.

Is this a known issue?

 

Share this post


Link to post
Share on other sites
BrewManNH

Try it without the @SW_HIDE so you can see if there's any errors showing. Also check the @error macro to see if there's an error returned, regardless of the exitcode.

Another thing, you might want to add a space before the /in command.


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

Share this post


Link to post
Share on other sites
ModemJunki

Thanks, BrewManNH. For ShellExecuteWait, the space is not needed. For RunWait it is.

I've tried:

$s_err = ShellExecuteWait($compileExe, $s_action)

And:

$s_err = RunWait($compileExe & " " & $s_action)

Still the same result.

So as a workaround I will go with adding something like:

If $s_err <> 0 Or Not FileExists(@ScriptDir & "\" & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe")) Then
; do error recording here
EndIf

But it would be interesting to know why this isn't working.

Share this post


Link to post
Share on other sites
Jos

tell me:

  • what version is this script compiled or running with (x86/x64)?
  • Which version of the aut2exe are you using as you never fill $compileExe in the shown code?
  • Do you see the same issue when they are the same OS architecture?

Jos


SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource        Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites
ModemJunki
3 hours ago, Jos said:

tell me:

  • what version is this script compiled or running with (x86/x64)?
  • Which version of the aut2exe are you using as you never fill $compileExe in the shown code?
  • Do you see the same issue when they are the same OS architecture?

Jos

To answer the first question: (version is in first post). Aut2exe.exe and Aut2exe_x64.exe show 3.3.14.5 in the details of their properties. As additional detail I am running on Windows 10 version 1703 build 15063.996 and there is running TrendMicro antivirus (corporate controlled), but I was able to see the same error on a Windows 10 environment that has only Windows Defender installed.

To answer the second question:

Global $compileExe86 = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Aut2Exe.exe", "")
Global $compileExe64 = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Aut2Exe_x64.exe", "") ; 64 bit recommended-> works 100% without WoW in WinPE X64, no issues with registry etc..

and (with the workaround in it), called as _CompileFiles("x86") or _CompileFiles("x64"):

Func _CompileFiles($s_arch) ; build the files
    Local $s_action, $s_err
    If $s_arch = "x86" Then
        $compileExe = $compileExe86
        $a_CompileFiles = $a_CompileFiles86
    ElseIf $s_arch = "x64" Then
        $compileExe = $compileExe64
        $a_CompileFiles = $a_CompileFiles64
    EndIf
    
    If IsArray($a_CompileFiles) Then
        ;~ _ArrayDisplay($a_CompileFiles,"$a_CompileFiles", "", 0 , "", "Index|Name|Destination")
        For $i = 1 To $a_CompileFiles[0][0]
            $s_prog = $s_prog + $s_Increment
            If FileExists($a_CompileFiles[$i][0]) Then
            _DoProgess($s_prog, Int($s_prog) & "% - Compiling file:" & @CRLF & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe"))
            If $s_arch = "x86" Then
                $s_action = "/in " & @ScriptDir & "\" & $a_CompileFiles[$i][0] & " /out " & @ScriptDir & "\" & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe") & " /pack /comp 4 /icon " & $icon & " /x86"; x86
            ElseIf $s_arch = "x64" Then
                $s_action = "/in " & @ScriptDir & "\" & $a_CompileFiles[$i][0] & " /out " & @ScriptDir & "\" & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe") & " /pack /comp 4 /icon " & $icon & " /x64" ; x64
            EndIf
            If Not @Compiled Then ConsoleWrite("Action is : " & $compileExe & " " & $s_action & @CRLF)
            $s_err = ShellExecuteWait($compileExe, $s_action, @ScriptDir, $SHEX_OPEN, @SW_HIDE)
            If Not @Compiled Then ConsoleWrite("@Error = " & @error & @CRLF)
            If Not @Compiled Then ConsoleWrite("$s_err = " & $s_err & @CRLF)

            If $s_err <> 0 Or Not FileExists(@ScriptDir & "\" & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe")) Then
                $s_err = $s_err + 1
                _ArrayAdd($a_result, "Error : There was an error compiling file " & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe") & ".")
            Else
                _ArrayAdd($a_result, "OK    : Compiled file " & $a_CompileFiles[$i][1] & "\" & StringReplace($a_CompileFiles[$i][0], ".au3", ".exe") & ".")
            EndIf
            _RunDos($cache_clear)

            Sleep(500)
            Else
            _ArrayAdd($a_result, "Error : File " & $a_CompileFiles[$i][0] & " was not found to compile.")
            EndIf
        Next
    EndIf
EndFunc   ;==>_CompileFiles

For the third question:

I made a test to have one of the files using FileInstall compiled as x86 and get the same result (normally I only compile some small tools for use in WinPE x86 where the x64 has no WoW subsystem and so cannot run the x64 files).

Odd detail you can ignore: In the function above, $cache_clear is "Global $cache_clear = @ScriptDir & "\sync64.exe", a Windows Sysinternals tool to flush the disk cache in Windows. I put that in there to deal with an odd problem I saw where sometimes the files were not compiled properly on high-performance SSD and NVMe drives in Windows 10.

I hope this helps to clarify the issue I'm seeing.

Share this post


Link to post
Share on other sites
ModemJunki

I've also tried this using the x86 compiler with the /x64 switch, the result is the same.

I'm not sure what else to try.

Can anyone else duplicate this problem, or is it just me?

Share this post


Link to post
Share on other sites
Jos

Are you getting any UAC prompt when running the compiled script?
If not: Could simply dumb it down to a few lines script with the hardcoded ShellExecute() and test logic so we can test with it? 

Jos


SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource        Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites
ModemJunki

No UAC, but that is because it's turned off.

I will work on making a simpler version of the script for testing, first I have to finish some stuff for the project I'm working on.

Share this post


Link to post
Share on other sites
Jos
11 minutes ago, ModemJunki said:

No UAC, but that is because it's turned off.

Not sure and hope somebody knows whether any process information is returned when the shelled process needs elevated rights without UAC enabled.
I am pretty sure it doesn't when UAC is Enabled.

Jos


SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource        Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

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

  • Similar Content

    • red0fireus
      By red0fireus
      When I run my script without compiling it, it works just fine.
      When I compile the script and run it this part of the script doesn't run properly. Here's my terrible explanation of what's supposed to happen but doesn't once its compiled.
      I have part of the script call the Function _Update well once it calls _Update it runs ShellExecute("C:\Test\test\run\Email.au3") immediately and doesn't wait 5 minutes. 
      $iMinutes = 5 $hTimer = TimerInit() Func _Update() AdlibRegister(_Update, 2000) If TimerDiff($hTimer) > ($iMinutes * 60000) And ProcessExists($recheck) Then ;ConsoleWrite("5 minutes have passed!" & @CRLF) ShellExecute("C:\Test\test\run\Email.au3") AdlibUnRegister(_Update) $hTimer = TimerInit() ElseIf Not ProcessExists($recheck) Then AdlibUnRegister(_Update) EndIf EndFunc Anyone have any suggestions on what I can do to fix this?
    • LFCavalcanti
      By LFCavalcanti
      Hi!
      Backstory to understand my need:
      I'm building something similar to what Chunk VNC was, using the Single Click function from UltraVNC to provide remote support.
      My "little monster" is actually working, but the "solution" will have 3 modules:
      SUPPORT: Users will open or install so IT Pros can access their system. VIEWER: IT Pros use to connect to User systems and perform their maintenance GENERATOR: The IT Pro uses to define the configuration for both the SUPPORT and VIEWER apps, like language files for text, SERVER address and ports, Company name, etc. I've attached a screenshot of the SUPPORT app that is done.
      Before anyone points the finger, no I'm not planning on just copying the AutoIt3 files to my project folder and distribute them, I intend to get the IT Pro who will use the GENERATOR to install SciTE and AutoIt3 then the GENERATOR will use them to compile the other two apps.
      The thing is, I need this to be simple, I thought about the GENERATOR having a single screen where the IT Pro can fill in all the information, select the language file and so on, then the GENERATOR compiles both "au3" sources for the SUPPORT and VIEWER.
      I'm using the ResourceEx UDF from Guiness and MetroUI UDF from BBs19. I even made some changes to the MEtroUI, that I shared here.
      This project will be uploaded to my Github account as soon I get this GENERATOR working, so people can actually use it.
      The problem:
      As explained, I need to compile the AU3 source files and perform an Resource Update. SciTE does that for me, right, but I just find sloppy making the GENERATOR open the script on the installed SciTE, clicking in the menus, waiting the process to end and then exit.
      When I hit the Compile or Build on SciTE, it generates this output:
       
      I've tried emulating this using the promt with console commands:
      It returns an error saying it was not possible to perform a resource update, poiting an TMP file on the ".../AppData/Local/AutoIt3/".
      As I understand, it runs the AutoIt3Wrapper, then the Wrapper should call the Aut2Exe to compile the script and then the Wrapper incorporate the resources into the compiled Script. It generates the file into a TMP one then copies to the directory defined in the Wrapper Directive.
      I know this seems strange, that you think I might be trying to pack AutoIt into my project with no F*** given, no... I just want to automate the compilation process, if there's no solution using console commands, I'll need to automate the process sending keyboard and mouse commands, what will be ugly and problematic.
      So... any help is a heaven's gift at this point.


    • hackersarchangel
      By hackersarchangel
      So I was looking at the self delete FAQ code and was wondering if there is a way for me to modify that to do a self compile.

      Basically, I want to be able to take my .exe, run it, have it unpack and change whatever files need changing, then recompile everything back into itself. I considered making a separate .exe so I could auto re-run the main.exe afterwards using a switch ,and I was also thinking I could make a placeholder file so the program would know it was just updated and run anything specific afterwards if I didn't make a separate .exe



      MsgBox(0,"Start","Starting self-compile attempt.") $iDelay = 0 Local $sCmdFile FileDelete(@TempDir & "update.bat") $sCmdFile = 'ping -n ' & $iDelay & ' 127.0.0.1 > nul' & @CRLF _ & ':loop' & @CRLF _ & @ScriptDir & 'UpdatesAut2exe.exe /in test.au3 /icon test.ico' & @CRLF _ & 'if exist "' & @ScriptDir & 'Updatestest.au3 goto loop' & @CRLF _ & 'Pause' FileWrite(@TempDir & "update.bat", $sCmdFile) Run(@TempDir & "update.bat", @TempDir, @SW_SHOW)



      Also, if I make an includes file, to list all of the files that would need including, would that be relative to that file, i.e

      This code would run the file from the main.exe being in the highest parent folder (like C: for example)


      ShellExecute(""Subfolderincludedsubfolderfile.exe"
      But in my subfolder: (example C:UpdateFileInstall.au3 and C:Updateextra_filesfile.exe)

      FileInstall("extra_filesfile.exe", "file.exe")
      If I was to #include that file into my main.exe, would it be placed in the right folder? I'm gonna test that theory in a bit, and post my findings. The basic thing is that if I was to re-compile the script, since that has to be a literal string, would prefer to not have to do a bunch of checking for those files to be in the right place lol.

      As I'm running this through my head, I'm realizing that one option would be to compile that into the other .exe (update.exe) and then just have an extract all switch like /e.

      Basic breakdown as I see it in my head: have the main.exe compile FileInstalling only the compiler and the update.exe files. The main.exe file would then extract the update.exe file and by default it would extract all files needed for running the sub programs. When going to update I would pass a switch /u to it so it would update any files, then recompile the main.exe. This is where the my need to possibly pass the command via the loopback into the computer would be needed. My testing shows that when going to run the compiler I need more time between the time I pass the command and the time it starts compiling due to it trying to pack the update.exe file and causing the compile to fail. One option I thought of was to do:


      FileInstall("Update.ex_","Update.ex_") FileInstall("Update.ex_","Update.exe")
      but someone else didn't like it because they was thinking it would double the size of the file. I'm gonna test that theory in a minute as well after I finish making my final edit xD


      Ok sorry for the massive post but this is a unique to me concept and was wondering if anyone else found this idea interesting and also had any advice.
×