Jump to content

Newbie question: How to wait till the end of the script?


Recommended Posts

Hello,

I try to automate Malwarebytes execution, which I'd like to put within a .bat file executing some night tasks. I do my tests in cmd window.

The issue I have, is the script execution in background. I launch my script using following syntax:

"C:\Program Files (x86)\AutoIt3\AutoIt3.exe" RunMalwareBytes.au3

The script starts and executes in background giving me a hand in cmd window at once.

My goal is to execute this script in foreground, and to get a hand at the end of the script execution, not before.

I was not able to find the solution for this issue neither in documentation nor on the forum.

Could you please help me in addressing this issue?

Thank you in advance

User3D

Link to comment
Share on other sites

hey there, welcome, you could always not use batch files, and use the script to everything instead..

Then you could control whether the window goes in background or not..

Do you absolutely have to run a batch file? Also i didn't quite get the hand problem you're talking about.

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

If you use function "Run" to execute another program you get the processid as a return value. In your main script you can check the PID for existance using function "ProcessExists".

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Hi,

Some more precisions.

The behaviour have now is:

1. I launch my script in cmd window (see original message for the syntax)

2. I get the cmd window prompt (and I can type another command)

3. The program window appears and it is controlled by the script

4. The program ends

5. Script ends with a defined return code

In my cmd window I cannot get this return code using %ERRORLEVEL% variable.

Also, I'm surprised by the value of @extended in my script, which seems to be time to time quite strange and not correspond to process return code. Also I'm surprised by the pid value, which can take a value about 300 and in the next launch 2 minutes later indicates the value bigger than 8000. I do not understand this point.

The behaviour I'd like to get is:

1. I launch the script

2. Program windows appears and it is controlled by the script

3. Program ends

4. script ends with a given return code

5. I get the cmd window

6. %ERRORLEVEL% contains script return code

My script (testing purpose) is at the bottom of this post (French used for displayed messages; file content written for testing purpose as this is the first script I started to write - it is quite far from its final version to come). It drives Malwarebytes database update correctly, but it requires some cleaning and it has to be updated to be able to install the new version of Malwarebytes.

I'd like to introduce it into the .bat script which manage the night tasks on my PC. This .bat script includes different scripts as other .bat files and vbs scripts. I do not wish to rewrite my night processing using AutoIt scripting language but to complete it with AutoIt scripts which I found very interesting and which seems to me answer the points I was not able to answer with other scripting languages.

I tried to use ConsoleWrite to display my test messages, but I didn't find where stdout was redirected. I cannot "see" it in my cmd window. For this reason I replaces ConsoleWrite by FileWriteLine using a test file toto.txt. Obviously in the final version of my script I will not use this French laziness style name.

All your comments are welcomed. Thank you for your help.

Bregs

User3D

#requireadmin

Local $Succes="Succès de la mise à jour de la base de données"

Local $Derniere="Vous avez la dernière version"

Local $Erreur="Une erreur"

Local $mode=0

Local $prog="C:Program Files (x86)Malwarebytesmbam.exe /update"

Local $file = FileOpen("toto.txt", 2)

; Check if file opened for writing OK

If $file = -1 Then

MsgBox(0, "Error", "Unable to open file.")

Exit

EndIf

MsgBox(0, "OK", "toto.txt opened")

Local $pid=Run($prog, "", @SW_MAXIMIZE )

if $pid = 0 Then

FileWriteLine($file, "Erreur lancement " & $prog & "n")

FileClose($file)

Exit ($mode)

EndIf

FileWriteLine($file, "Lancement " & $prog & " pid=" & $pid & " n")

WinWaitActive("Malwarebytes Anti-Malware")

Local $text = WinGetText("Malwarebytes Anti-Malware")

FileWriteLine($file, "Texte de la fenetre = " & $text & "n")

if StringInStr($text, $Erreur) > 0 Then

$mode=1

FileWriteLine($file, "Erreur mise a jour n")

ElseIf StringInStr($text, $Derniere) > 0 Then

$mode=0

FileWriteLine($file, "La dernière version est dejà installée")

ElseIf StringInStr($text,, $Succes) > 0 Then

$mode=0

FileWriteLine($file, "mise à jour reussie n")

Else

$mode=2

FileWriteLine($file, "Le logiciel doit etre mis a jour n")

EndIf ;fin test resultats update

Send("{ENTER}")

WinWaitNotActive("Malwarebytes Anti-Malware")

$mode=ProcessWaitClose($pid)

FileWriteLine($file, "Fin process " & $pid & " code retour = " & @extended & "n")

FileClose($file)

Exit (@extended)

Link to comment
Share on other sites

Hey and welcome to the forum :)

I think the answer you are looking for is here:

Short version: you should get correct %ERRORLEVEL% value if you run your autoit script from a .bat file and not from the CMD prompt.

Cheers from Montpellier :)

PS: when you post Autoit code in this forum, use:

[.autoit] (without the ".")

your code

[./autoit] (without the ".")

It shows your code like this:

#requireadmin
Local $Succes="Succès de la mise à jour de la base de données"
Local $Derniere="Vous avez la dernière version"
Local $Erreur="Une erreur"
Local $mode=0
Local $prog="C:\Program Files (x86)\Malwarebytes\mbam.exe /update"
Local $file = FileOpen("toto.txt", 2)
; Check if file opened for writing OK
If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf
MsgBox(0, "OK", "toto.txt opened")
Local $pid=Run($prog, "", @SW_MAXIMIZE )
if $pid = 0 Then
   FileWriteLine($file, "Erreur lancement " & $prog & "\n")
   FileClose($file)
   Exit ($mode)
EndIf
FileWriteLine($file, "Lancement " & $prog & " pid=" & $pid & " \n")
WinWaitActive("Malwarebytes Anti-Malware")
Local $text = WinGetText("Malwarebytes Anti-Malware")
FileWriteLine($file, "Texte de la fenetre = " & $text & "\n")
if StringInStr($text, $Erreur) > 0 Then
   $mode=1
   FileWriteLine($file, "Erreur mise a jour \n")
ElseIf StringInStr($text, $Derniere) > 0 Then
   $mode=0
   FileWriteLine($file, "La dernière version est dejà installée")
ElseIf StringInStr($text,, $Succes) > 0 Then
   $mode=0
   FileWriteLine($file, "mise à jour reussie \n")
Else
   $mode=2
   FileWriteLine($file, "Le logiciel doit etre mis a jour \n")
EndIf ;fin test resultats update
Send("{ENTER}")
WinWaitNotActive("Malwarebytes Anti-Malware")
$mode=ProcessWaitClose($pid)
FileWriteLine($file, "Fin process " & $pid & " code retour = " & @extended & "\n")
FileClose($file)
Exit (@extended)
Edited by Neutro
Link to comment
Share on other sites

Hi,

Thank you for your answers.

Finally, I decided to synchronize .bat and .au3 scripts using the file in which I put the results of update as semaphore. I put hereafter the current version of my .au3 script. Within the comments, I put the example of .bat script, which waits till the end of .au3 script and, when returns, sets %ERRORLEVEL% to the value indicated by .au3.

Bregs

User3D

PS.

Neutro, thanks for the advice how to post AutoIt code. Here follows my try. Also the Paris area is not that sunny as the Montpelier one. It's a pity...

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.8.1
 Author:         Jacek
 Script version: 01a
 Use: "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" UpdateMalwareBytes.au3 [<SemaphoreFile>]

 Script Function:
              Malwarebytes database update
              Based on French language Malwarebytes installation
             
              This script collaborates with .bat file, which waits till the end of the update and sets %ERRORLEVEL%
              To synchronize both scripts a file <SemaphoreFile> with script results is used.
              At the end of database update, the .au3 scripts renames <SemaphoreFile> adding ".txt" suffix
              The .bat script checks every 5 second if <SemaphoreFile>.txt exists. Whne the file found,
              .bat script prints its content, looks for return code and exits setting %ERRORLEVEL% to the value found in
              <SemaphoreFile>.txt. If ReturnCode not fount, .bat scripts sets %ERRORLEVEL% to -1
             
              Example of .bat script which waits for the end of Malware database update:
             
                @echo OFF
                set SemaphoreFile=tsem
                set timer=5
                del %SemaphoreFile%.txt >nul
                echo " INFO: recherches malware avec MALWAREBYTES: mise à jour de base de donnees"
                start /wait "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" UpdateMalwareBytes.au3 %SemaphoreFile%

                :NotFinished
                if NOT EXIST %SemaphoreFile%.txt (
                            ping localhost -n %timer% >nul
                            GOTO NotFinished
                            )
                echo " INFO: Resultats de la mise a jour de la base dans le fichier " %SemaphoreFile%.txt " :"
                type %SemaphoreFile%.txt | find /I /V "ReturnCode"
                For /F "tokens=1,2* delims=: " %%i in (%SemaphoreFile%.txt) DO if %%i==ReturnCode exit /B %%j
                exit /B -1
             

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
; This script requires full Administrative rights
#requireadmin

Const $prog="C:\Program Files (x86)\Malwarebytes\mbam.exe /update"
Const $WinTitle="Malwarebytes Anti-Malware" ; Malwarebytes window title
; Malwarebytes window text to be tested
Const $Succes="Succès de la mise à jour de la base de données"
Const $Derniere="Vous avez la dernière version"
Const $Erreur="Une erreur"

Const $DefautName="MlwUpdRes"    ; file name to be used if <SemaphoreFile> parameter is absent
Const $suffix=".txt"                                  ; suffix to be added
Const $OVERWRITE=1

If $CmdLine[0]>0 Then
   $name=$CmdLine[1]
Else
   $name=$DefautName
EndIf

Local $mode=0
Local $file = FileOpen($name, 2)


; Check if file opened for writing OK
If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file", & $name)
    Exit
EndIf

; Administration rights check
if IsAdmin()= 0 Then
   FileWriteLine($file, "Script doit être execute avec les droits d'administrateur " & @CRLF)
   FinScript($file, $name, 9)
EndIf

; database update launch
Local $pid=Run($prog, "" )
if $pid = 0 Then
   FileWriteLine($file, "Erreur lancement " & $prog & @CRLF)
   FinScript($file, $name, 2)
EndIf

WinWaitActive($WinTitle)

Local $text = WinGetText($WinTitle)
FileWriteLine($file, @CRLF & StringTrimLeft($text, 2) & @CRLF)
;Succès de la mise à jour de la base de données, de la version v2013.04.04.07 vers la version v2013.04.21.05.
;Vous avez la dernière version de la base de données.

if StringInStr($text, $Erreur) > 0 Then ; update error
   $mode=1
   FileWriteLine($file, "* Erreur mise a jour de la base Malwarebytes" & @CRLF)
ElseIf StringInStr($text, $Derniere) > 0 Then ; databease is already up-to-date
   $mode=0
ElseIf StringInStr($text, $Succes) > 0 Then ;update succesful
   $mode=0
Else ; update to by done by hand
   $mode=2
   FileWriteLine($file, "* Le logiciel et la base de donnees doivent etre mis a jour manuellement" & @CRLF)
   WinKill($WinTitle)
   $i=ProcessClose($pid)
   if $i=0 Then
                FileWriteLine($file, "Erreur fermeture process=" & @error & @CRLF)
                $mode=3
   EndIf
   FinScript($file, $name, $mode)
EndIf ; end of the results tests

Send("{ENTER}")
WinWaitNotActive($WinTitle)

$i=ProcessWaitClose($pid)

FinScript($file, $name, $mode)

; end of script function
; its role is to write in optput file teh reurn code value and rename this file by adding $suffix
; it end the script

Func FinScript($file, $nom, $return)
   FileWriteLine($file, "ReturnCode:"  & $return & @CRLF)
   FileClose($file)
   $i=FileMove($nom, $nom & $suffix, $OVERWRITE)
   If $i = 0 Then
                MsgBox(0, "Error", "Unable to rename file" & $nom & " onto " & $nom & $suffix)
                Exit
   EndIf
   Exit ($return)
EndFunc
Link to comment
Share on other sites

Hi,

The script, I put yesterday in my answer, works fine if launched from a user session. It does not work when launched by Task Scheduler, as the functions used works only on active windows (this is my last discovery). Finally, I find the method how to arrange the script to make it work when launched by scheduler. This is explained in FAQ (but as a standard “Newbie” I’m not that fond of reading the FAQ, thus I wasted some my time and perhaps also some time of the others, who answered my post).

Thus finally I have a script which works. Launched from .bat file, it updates Malwarebytes database and performs the scan. It does not remove any infection, but if any malware found, it invites in its result file to preform manual scan. I does not perform the installation of a new software version, neither. These two actions are left to be done by the user, and perhaps for some future developments.

As the previous version of the script does not works correctly, I attached to this post the one, which can be launched using Task Scheduler. Perhaps someone will find useful.

Brges

User3D

#cs ----------------------------------------------------------------------------

AutoIt Version: 3.3.8.1
Author:      Jacek
Script version: 01c
Use: "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" RunMalwareBytes.au3 [<SemaphoreFile>]

Script Function:
             Malwarebytes database update
             Based on French language Malwarebytes installation
            
             This script collaborates with .bat file, which waits till the end of the update and sets %ERRORLEVEL%
             To synchronize both scripts a file <SemaphoreFile> containing script results is used.
             At the end of the .au3 script, it renames <SemaphoreFile> adding ".txt" suffix
             The .bat script checks every 5 seconds if <SemaphoreFile>.txt exists. Whne the file found,
             .bat script prints its content, looks for return code and exits setting %ERRORLEVEL% to the value found in
             <SemaphoreFile>.txt. If ReturnCode not found, .bat script sets %ERRORLEVEL% to -1
            
             Example of .bat script which waits for the end of Malware database update:
            
             @echo OFF
             set SemaphoreFile=tsem
             set timer=5
             del %SemaphoreFile%.txt >nul
             echo " INFO: recherches malware avec MALWAREBYTES: mise à jour de base de donnees"
             start /wait "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" RunMalwareBytes.au3 %SemaphoreFile%

             :NotFinished
             if NOT EXIST %SemaphoreFile%.txt (
                         ping localhost -n %timer% >nul
                         GOTO NotFinished
                         )
             echo " INFO: Resultats de la mise a jour de la base dans le fichier " %SemaphoreFile%.txt " :"
             type %SemaphoreFile%.txt | find /I /V "ReturnCode"
             For /F "tokens=1,2* delims=: " %%i in (%SemaphoreFile%.txt) DO if %%i==ReturnCode exit /B %%j
             exit /B -1
            

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here
; This script requires full Administrative rights
#requireadmin

Global Const $prog="C:\Program Files (x86)\Malwarebytes\mbam.exe "       ; Malwarebytes program
Global Const $WinTitle="Malwarebytes Anti-Malware"                                                               ; Malwarebytes window title
; messages to be displayed
Global Const $MalwareDetected="LOGICIEL MALVEILLANT DETECTE - Lancer Malwarebytes manuellement et supprimer le logiciel malveillant" & @CRLF & "Rapport d'analyse:" & @CRLF
Global Const $MalwareNotDetected="Malware non detecte"
Global Const $AdminRequired="Script doit être execute avec les droits d'administrateur "
; Malwarebytes window text to be tested
Global Const $Succes="Succès de la mise à jour de la base de données"
Global Const $Derniere="Vous avez la dernière version"
Global Const $Erreur="Une erreur"
Global Const $SansMalware="normalement. Aucun"

Const $DefautName="MlwUpdRes"    ; file name to be used if <SemaphoreFile> parameter is absent
Global Const $suffix=".txt"                  ; suffix to be added
Global Const $LAST="[LAST]"              ; last addressed window
Const $OVERWRITE=2                                       ; file open mode

; get filename (either fron the first parammeter - if exists - or take the defult one
If $CmdLine[0]>0 Then
$name=$CmdLine[1]
Else
$name=$DefautName
EndIf

Local $mode=0
Global $file = FileOpen($name, 2)        ; File result opening
; Check if file opened for writing OK
If $file = -1 Then
MsgBox(0, "Error " & @error, "Unable to open file" & $name)
Exit
EndIf

; Administration rights check
if IsAdmin()= 0 Then
FileWriteLine($file, $AdminRequired & @CRLF)
FinScript($file, $name, 8)
EndIf
$i=AutoItSetOption("WinDetectHiddenText", 1) ; as the script is launched by Task Scheduler, it will have to read hidden windows
; database update launch
Local $upd = DataBaseUpdate("/update")

; Scan for Malware
$mode=ComputerScan("/scan")
If $mode = 0 Then
$mode = $upd
EndIf

;end of script
FinScript($file, $name, $mode)

;------------------------------------

;------------------------------------ Functions
; Computer scan

Func ComputerScan($param)
FileWriteLine($file, "Computer scan: " & $prog & $param & @CRLF)
$mode=20
Local $pid=Run($prog & $param, "" )
if $pid = 0 Then
             FileWriteLine($file, "Erreur lancement " & $prog & $param & @CRLF)
             $mode = 20
Else
             WinWait("[CLASS:Notepad]")
             $text1 = WinGetText($LAST)
             WinClose($LAST)
            
             WinWait("[TITLE:" & $WinTitle & ";CLASS:#32770]")
             $text2 = WinGetText($LAST)
             ControlClick($LAST, "", "Button1")
            
             WinWait("[TITLE:" & $WinTitle & ";CLASS:ThunderRT6FormDC]")
             $text3 = WinGetText($LAST)
             ControlClick($LAST, "", "ThunderRT6CommandButton6")
            
             $i=ProcessWaitClose($pid)
            
             if StringInStr($text2, $SansMalware) > 0 Then ; malware not found
                         FileWriteLine($file, $MalwareNotDetected)
                         ;FileWriteLine($file, @CRLF & StringTrimLeft($text2, 2) & @CRLF)
                         $mode=0
             Else
                         $mode=9
                         FileWriteLine($file, $MalwareDetected)
                         FileWriteLine($file, @CRLF & $text1 & @CRLF)
             EndIf
EndIf

Return $mode
EndFunc


;------------------------------------
; Malwarebytes database update function

Func DataBaseUpdate($param)
Local $pid=Run($prog & $param, "" )
if $pid = 0 Then
             FileWriteLine($file, "Erreur lancement " & $prog & $param & @CRLF)
             FinScript($file, $name, 2)
EndIf

Local $hndl=WinWait("[TITLE:" & $WinTitle & ";CLASS:#32770]")
Local $text = WinGetText($LAST)
FileWriteLine($file, @CRLF & StringTrimLeft($text, 2) & @CRLF)
;Succès de la mise à jour de la base de données, de la version v2013.04.04.07 vers la version v2013.04.21.05.
;Vous avez la dernière version de la base de données.

if StringInStr($text, $Erreur) > 0 Then ; update error
             $mode=1
             FileWriteLine($file, "* Erreur mise a jour de la base Malwarebytes" & @CRLF)
ElseIf StringInStr($text, $Derniere) > 0 Then ; databease is already up-to-date
             $mode=0
ElseIf StringInStr($text, $Succes) > 0 Then ;update succesful
             $mode=0
Else ; update to by done by hand
             $mode=2
             FileWriteLine($file, "* Le logiciel et la base de donnees doivent etre mis a jour manuellement" & @CRLF)
             WinKill($LAST)
             $i=ProcessClose($pid)
             if $i=0 Then
                         FileWriteLine($file, "Erreur fermeture process=" & @error & @CRLF)
                         $mode=3
             EndIf
EndIf ; end of the results tests
if NOT ($mode = 3) Then
             ControlClick($LAST, "", "Button1")
             WinWaitNotActive($LAST)
             $i=ProcessWaitClose($pid)
EndIf
Return $mode
EndFunc

;------------------------------------
; end of script function
; its role is to write in optput file teh reurn code value and rename this file by adding $suffix
; it end the script

Func FinScript($file, $nom, $return)
FileWriteLine($file, "ReturnCode:" & $return & @CRLF)
FileClose($file)
$i=FileMove($nom, $nom & $suffix, $OVERWRITE)
If $i = 0 Then
             MsgBox(0, "Error", "Impossibble de renommer fichier " & $nom & " en " & $nom & $suffix)
             Exit
EndIf
Exit ($return)
EndFunc
Link to comment
Share on other sites

Use controlgettext rather than wingettext...also set this at the top of your script:

AutoItSetOption("WinDetectHiddenText", 1)

If you are running as scheduled task, the window is hidden along with the text (runs on session 0).

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.
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...