mihaijulien

Error: array variable has incorrect number of subscripts or subscript dimension range exceeded

23 posts in this topic

#1 ·  Posted

Hello,

I compiled a script I made that takes a command line parameter (the version of a .msi installer) when launched. The script was compiled with the /console option. The script (.au3) works fine but the executable returns  the following error:  

Error: array variable has incorrect number of subscripts or subscript dimension range exceeded

 

Share this post


Link to post
Share on other sites



#2 ·  Posted

The script doesn't work fine as you can see so there must be a condition that a function doesn't return an expected Array and you aren't testing for that condition.

Without a script we won't be able to assist.

Jos


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#3 ·  Posted

Here is the code:

#RequireAdmin

#include <FileConstants.au3>
#include <WinAPIShPath.au3>
#include "UDF\log4a.au3"

Opt("WinTitleMatchMode",2)

Global $defaultLocation = "C:\Program Files\MyApp\" & $CmdLine
Global $CmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)

Install()
$processes = _MyProcessList("MyApp")
If ProcessExists($processes[1]) Then
   LogInfo("App service started succesfully")
EndIf
_ProcessCloseEx($processes[1]) ;kill App & child processes

Func Install()

   Local $hWnd = "MyApp " & $CmdLine[2] &" Setup"
   Local $installer = "myapp-win-installer-" & $CmdLine[2] &".msi"

   ShellExecute($installer,"",@ScriptDir & "\installers")
   If @error Then
      LogInfo("Error when starting the installer")
      Return
   EndIf

   While Not ControlCommand($hWnd,"","[Text:&Next >]", "IsEnabled",'')
      Sleep(500)
      ;if the app is already installed, close the install wizard
      If ControlGetText($hWnd,"","[Text:Remove Installation]") Then
         LogError("Error: MyApp is already installed")
         Sleep(1000)
         WinClose($hWnd)
         Return
      EndIf

   WEnd

   ControlClick($hWnd,"","[CLASS:Button; INSTANCE:1]") ;first Next ;1572
   Local $counter = 0
   For $counter = 0 to 1
      Send("{TAB}")
      Sleep(100)
   Next
   Send("{UP}") ;accept the terms in the License Agreement ;57
   Sleep(100)
   ControlClick($hWnd,"","[CLASS:Button; INSTANCE:1]") ; Next ;1572
   Sleep(500)
   ControlClick($hWnd,"","[CLASS:Button; INSTANCE:5]") ; uncheck app start ;3281
   Sleep(500)
   ;install the app at the default location
   ControlClick($hWnd,"","[CLASS:Button; INSTANCE:1]") ; Next ;1572
   Sleep(500)
   If WinExists($hWnd, "Port Conflict Found") Then
      ControlClick($hWnd, "","[CLASS:Button; INSTANCE:4]")
      Sleep(500)
      ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
   EndIf

   WinWaitActive("MyApp Test")
   ControlClick("MyApp Test","","[CLASS:Button; INSTANCE:1]") ;Ok on the test


   ; wait the install successful UI
   While 1
      $var = ControlGetText($hWnd, "", "[Text:&Finish]")

      If $var == "&Finish" Then

      ControlClick($hWnd,"","[CLASS:Button; INSTANCE:1]") ;Finish

         ExitLoop
      EndIf
      Sleep(1000)
   WEnd

EndFunc

;kill processes
Func _ProcessCloseEx($sPID)
    If IsString($sPID) Then $sPID = ProcessExists($sPID)
    If Not $sPID Then Return SetError(1, 0, 0)

    Return Run(@ComSpec & " /c taskkill /F /PID " & $sPID & " /T", @SystemDir, @SW_HIDE)
 EndFunc

 ;retrieve processes using partial name string as parameter
 Func _MyProcessList($str)

    Local $alist = ProcessList(), $ret
    For $1 = 0 To UBound($alist) - 1
        If StringInStr($alist[$1][0], $str) Then $ret &= $alist[$1][0] & '|'
    Next

    Return StringSplit(StringTrimRight($ret, 1), '|')

EndFunc

The .au3 works fine.

Share this post


Link to post
Share on other sites

#4 ·  Posted

Can't test as I don't haave the include you use, but my guess is that $ret remains empty in Func _MyProcessList , hence not returning an Array, thus triggering an error in the next statement testing for $processes[1]. Does this work?

Func _MyProcessList($str)

    Local $alist = ProcessList(), $ret="|"
    For $1 = 0 To UBound($alist) - 1
        If StringInStr($alist[$1][0], $str) Then $ret &= $alist[$1][0] & '|'
    Next

    Return StringSplit(StringTrimRight($ret, 1), '|')

EndFunc   ;==>_MyProcessList

 


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#5 ·  Posted

Hello,

I don't think it's relevant what it's in the UDF folder that I included, but here it is attached. The script above works just fine when not compiled.

 

UDF.7z

Share this post


Link to post
Share on other sites

#7 ·  Posted

I am unsure what the intent of the concatenation of the first line should do as $CmdLine is an Array.

I actually think the second line in this part could also be giving problems when $CmdLineRaw is empty.
Also wouldn't use $CmdLine as that in an internal constant but something else like:

Global $defaultLocation = "C:\Program Files\MyApp\" & $CmdLine
Global $sCmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)
if UBound($sCmdLine) < 3 then
    ; there are not enough parameters specified
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $CmdLineRaw = ' & $CmdLineRaw & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
EndIf

;~ Install()
$processes = _MyProcessList("MyApp")
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $processes[1] = ' & $processes[1] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
If ProcessExists($processes[1]) Then
;~  LogInfo("App service started succesfully")
EndIf
_ProcessCloseEx($processes[1]) ;kill App & child processes

Func Install()

    Local $hWnd = "MyApp " & $sCmdLine[2] & " Setup"
    Local $installer = "myapp-win-installer-" & $sCmdLine[2] & ".msi"

Jos


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#8 ·  Posted

The script works just fine when it isn't compiled. When launching the .exe, I have the error from the attached file.

It's pretty strange.

error.png

Share this post


Link to post
Share on other sites

#9 ·  Posted

Have you tried my suggestions, as repeating what I already know doesn't help much. ...  and no, it is not per se strange that it works uncompiled and erros compiled when the issue is around commandline parameters as with the uncompiled version, there always are parameters supplied to run the script.

So pls start testing and providing more exact information.

Jos


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Simple question:

How exactly do you run the console exe, and how exactly to you run the app exe?

I'm assuming that you are expecting the console parameters you use to be compiled into the app exe...which will not happen.

 

Edit, if the above is not related...you should update your script to not assume that arrays are created, and have the proper amount of subscripts...you should include error handling that validates the UBound of all dimensions....such as, if it's not as large as you expect, throw a msgbox stating where in the script you are, so you can fix it...then exit.

Edited by jdelaney

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.

Share this post


Link to post
Share on other sites

#11 ·  Posted

Well, I open a cmd and I type "InstallScript.au3 5.0". I launch the executable in the same way: "InstallScript.exe 5.0". The first works, the second doesn't. I'm still trying to figure out what might be the problem.

Share this post


Link to post
Share on other sites

#12 ·  Posted

Good lucky:

#RequireAdmin
Opt("TrayAutoPause", 0)
Opt("WinTitleMatchMode", 2)

Global $CmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)
If @error Then Exit _WriteLog("! Not enter comnand line!", @ScriptLineNumber)

Install()

Global $processes = _MyProcessList("MyApp")
If Not @error And IsArray($processes) Then
    If ProcessExists($processes[1]) Then
        _WriteLog("+ App service started succesfully", @ScriptLineNumber)
    EndIf
    _ProcessCloseEx($processes[1])
Else
    _WriteLog("! App service not started", @ScriptLineNumber)
EndIf

Func Install()
    Local $hWnd = "MyApp " & $CmdLine[2] & " Setup"
    Local $installer = "myapp-win-installer-" & $CmdLine[2] & ".msi"
    ShellExecute($installer, "", @ScriptDir & "\installers")
    If @error Then
        _WriteLog("Error when starting the installer", @ScriptLineNumber)
        Return
    EndIf
    While (Not ControlCommand($hWnd, "", "[Text:&Next >]", "IsEnabled", ''))
        Sleep(500)
        If ControlGetText($hWnd, "", "[Text:Remove Installation]") Then
            _WriteLog("Error: MyApp is already installed", @ScriptLineNumber)
            Sleep(1000)
            WinClose($hWnd)
            Return
        EndIf
    WEnd
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Local $counter = 0
    For $counter = 0 To 1
        Send("{TAB}")
        Sleep(100)
    Next
    Send("{UP}")
    Sleep(100)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:5]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    If WinExists($hWnd, "Port Conflict Found") Then
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:4]")
        Sleep(500)
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    EndIf
    WinWaitActive("MyApp Test")
    ControlClick("MyApp Test", "", "[CLASS:Button; INSTANCE:1]")
    Local $var
    While 1
        $var = ControlGetText($hWnd, "", "[Text:&Finish]")
        If $var == "&Finish" Then
            ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
            ExitLoop
        EndIf
        Sleep(1000)
    WEnd
EndFunc   ;==>Install
Func _ProcessCloseEx($sPID)
    If IsString($sPID) Then $sPID = ProcessExists($sPID)
    If Not $sPID Then Return SetError(1, 0, 0)
    Return Run(@ComSpec & " /c taskkill /F /PID " & $sPID & " /T", @SystemDir, @SW_HIDE)
EndFunc   ;==>_ProcessCloseEx
Func _MyProcessList($str)
    Local $alist = ProcessList(), $ret
    If $alist[0][0] <> 0 Then
        For $1 = 0 To UBound($alist) - 1
            If StringInStr($alist[$1][0], $str) Then $ret &= $alist[$1][0] & '|'
        Next
        Return StringSplit(StringTrimRight($ret, 1), '|')
    EndIf
    Return SetError(1, 0, "")
EndFunc   ;==>_MyProcessList
;
Func _WinAPI_GetString($pString, $bUnicode = True)
    Local $iLength = _WinAPI_StrLen($pString, $bUnicode)
    If @error Or Not $iLength Then Return SetError(@error + 10, @extended, '')
    Local $tString = DllStructCreate(__Iif($bUnicode, 'wchar', 'char') & '[' & ($iLength + 1) & ']', $pString)
    If @error Then Return SetError(@error, @extended, '')
    Return SetExtended($iLength, DllStructGetData($tString, 1))
EndFunc   ;==>_WinAPI_GetString
Func _WinAPI_StrLen($pString, $bUnicode = True)
    Local $W = ''
    If $bUnicode Then $W = 'W'
    Local $aRet = DllCall('kernel32.dll', 'int', 'lstrlen' & $W, 'struct*', $pString)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>_WinAPI_StrLen
Func __Iif($bTest, $vTrue, $vFalse)
    Return $bTest ? $vTrue : $vFalse
EndFunc   ;==>__Iif
Func _WinAPI_CommandLineToArgv($sCmd)
    Local $aResult[1] = [0]
    $sCmd = StringStripWS($sCmd, 1 + 2)
    If Not $sCmd Then
        Return $aResult
    EndIf
    Local $aRet = DllCall('shell32.dll', 'ptr', 'CommandLineToArgvW', 'wstr', $sCmd, 'int*', 0)
    If @error Or Not $aRet[0] Or (Not $aRet[2]) Then Return SetError(@error + 10, @extended, 0)
    Local $tPtr = DllStructCreate('ptr[' & $aRet[2] & ']', $aRet[0])
    Dim $aResult[$aRet[2] + 1] = [$aRet[2]]
    For $i = 1 To $aRet[2]
        $aResult[$i] = _WinAPI_GetString(DllStructGetData($tPtr, 1, $i))
    Next
    DllCall("kernel32.dll", "handle", "LocalFree", "handle", $aRet[0])
    Return $aResult
EndFunc   ;==>_WinAPI_CommandLineToArgv
Func _WriteLog($iLine, $sLine = "")
    Local $iTime = ($sLine == "") ? @HOUR & @MIN & @SEC & ": " & $iLine : @HOUR & @MIN & @SEC & "_ScriptLine-" & $sLine & ": " & $iLine
    FileWriteLine(@ScriptName & ".log", $iTime)
    ConsoleWrite($iTime & @CRLF)
EndFunc   ;==>_WriteLog

 


Regards,
 

Share this post


Link to post
Share on other sites

#13 ·  Posted

1 hour ago, Trong said:

Good lucky:

#RequireAdmin
Opt("TrayAutoPause", 0)
Opt("WinTitleMatchMode", 2)

Global $CmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)
If @error Then Exit _WriteLog("! Not enter comnand line!", @ScriptLineNumber)

Install()

Global $processes = _MyProcessList("MyApp")
If Not @error And IsArray($processes) Then
    If ProcessExists($processes[1]) Then
        _WriteLog("+ App service started succesfully", @ScriptLineNumber)
    EndIf
    _ProcessCloseEx($processes[1])
Else
    _WriteLog("! App service not started", @ScriptLineNumber)
EndIf

Func Install()
    Local $hWnd = "MyApp " & $CmdLine[2] & " Setup"
    Local $installer = "myapp-win-installer-" & $CmdLine[2] & ".msi"
    ShellExecute($installer, "", @ScriptDir & "\installers")
    If @error Then
        _WriteLog("Error when starting the installer", @ScriptLineNumber)
        Return
    EndIf
    While (Not ControlCommand($hWnd, "", "[Text:&Next >]", "IsEnabled", ''))
        Sleep(500)
        If ControlGetText($hWnd, "", "[Text:Remove Installation]") Then
            _WriteLog("Error: MyApp is already installed", @ScriptLineNumber)
            Sleep(1000)
            WinClose($hWnd)
            Return
        EndIf
    WEnd
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Local $counter = 0
    For $counter = 0 To 1
        Send("{TAB}")
        Sleep(100)
    Next
    Send("{UP}")
    Sleep(100)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:5]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    If WinExists($hWnd, "Port Conflict Found") Then
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:4]")
        Sleep(500)
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    EndIf
    WinWaitActive("MyApp Test")
    ControlClick("MyApp Test", "", "[CLASS:Button; INSTANCE:1]")
    Local $var
    While 1
        $var = ControlGetText($hWnd, "", "[Text:&Finish]")
        If $var == "&Finish" Then
            ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
            ExitLoop
        EndIf
        Sleep(1000)
    WEnd
EndFunc   ;==>Install
Func _ProcessCloseEx($sPID)
    If IsString($sPID) Then $sPID = ProcessExists($sPID)
    If Not $sPID Then Return SetError(1, 0, 0)
    Return Run(@ComSpec & " /c taskkill /F /PID " & $sPID & " /T", @SystemDir, @SW_HIDE)
EndFunc   ;==>_ProcessCloseEx
Func _MyProcessList($str)
    Local $alist = ProcessList(), $ret
    If $alist[0][0] <> 0 Then
        For $1 = 0 To UBound($alist) - 1
            If StringInStr($alist[$1][0], $str) Then $ret &= $alist[$1][0] & '|'
        Next
        Return StringSplit(StringTrimRight($ret, 1), '|')
    EndIf
    Return SetError(1, 0, "")
EndFunc   ;==>_MyProcessList
;
Func _WinAPI_GetString($pString, $bUnicode = True)
    Local $iLength = _WinAPI_StrLen($pString, $bUnicode)
    If @error Or Not $iLength Then Return SetError(@error + 10, @extended, '')
    Local $tString = DllStructCreate(__Iif($bUnicode, 'wchar', 'char') & '[' & ($iLength + 1) & ']', $pString)
    If @error Then Return SetError(@error, @extended, '')
    Return SetExtended($iLength, DllStructGetData($tString, 1))
EndFunc   ;==>_WinAPI_GetString
Func _WinAPI_StrLen($pString, $bUnicode = True)
    Local $W = ''
    If $bUnicode Then $W = 'W'
    Local $aRet = DllCall('kernel32.dll', 'int', 'lstrlen' & $W, 'struct*', $pString)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>_WinAPI_StrLen
Func __Iif($bTest, $vTrue, $vFalse)
    Return $bTest ? $vTrue : $vFalse
EndFunc   ;==>__Iif
Func _WinAPI_CommandLineToArgv($sCmd)
    Local $aResult[1] = [0]
    $sCmd = StringStripWS($sCmd, 1 + 2)
    If Not $sCmd Then
        Return $aResult
    EndIf
    Local $aRet = DllCall('shell32.dll', 'ptr', 'CommandLineToArgvW', 'wstr', $sCmd, 'int*', 0)
    If @error Or Not $aRet[0] Or (Not $aRet[2]) Then Return SetError(@error + 10, @extended, 0)
    Local $tPtr = DllStructCreate('ptr[' & $aRet[2] & ']', $aRet[0])
    Dim $aResult[$aRet[2] + 1] = [$aRet[2]]
    For $i = 1 To $aRet[2]
        $aResult[$i] = _WinAPI_GetString(DllStructGetData($tPtr, 1, $i))
    Next
    DllCall("kernel32.dll", "handle", "LocalFree", "handle", $aRet[0])
    Return $aResult
EndFunc   ;==>_WinAPI_CommandLineToArgv
Func _WriteLog($iLine, $sLine = "")
    Local $iTime = ($sLine == "") ? @HOUR & @MIN & @SEC & ": " & $iLine : @HOUR & @MIN & @SEC & "_ScriptLine-" & $sLine & ": " & $iLine
    FileWriteLine(@ScriptName & ".log", $iTime)
    ConsoleWrite($iTime & @CRLF)
EndFunc   ;==>_WriteLog

 

Works perfectly when running the .au3, after I compile it (x64) it no longer works, same error. (but this time the error is on Line 17). :/

Share this post


Link to post
Share on other sites

#14 ·  Posted

Funny how you seem to ignore the pointers I have given you and you persisting to repeat it isn't working.
Just for the last time: Have you tested the possible solution I gave? 
Do you understand what I have tried to tell you?
Do you have any question about it?

Jos
 


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#15 ·  Posted

9 minutes ago, Jos said:

Funny how you seem to ignore the pointers I have given you and you persisting to repeat it isn't working.
Just for the last time: Have you tested the possible solution I gave? 
Do you understand what I have tried to tell you?
Do you have any question about it?

Jos
 

Sorry I didn't reply, but yes, I tried my scripts with your suggestions (changing the default $CmdLine to $sCmdLine.

Share this post


Link to post
Share on other sites

#16 ·  Posted

.... and?

Did you get the console prompt? ( Maybe you need to change that to a MSGBOX() so it always shows!
You really need to learn to start providing information and help testing when you want your issue to be resolved! ;)

Try replacing that added test with this version:

Global $defaultLocation = "C:\Program Files\MyApp\" & $CmdLine
Global $sCmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)
if UBound($sCmdLine) < 3 then
    MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @CRLF & '$CmdLineRaw' & @CRLF & @CRLF & 'Return:' & @CRLF & $CmdLineRaw)
    Exit
EndIf

The script will exit after showing the msgbox() in case there are not enough parameters provided.

Jos


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#17 ·  Posted

Bad script:

#RequireAdmin
Opt("TrayAutoPause", 0)
Opt("WinTitleMatchMode", 2)


Global $sCmdLineRaw = @Compiled ? $CmdLineRaw : "" ;StringReplace($CmdLineRaw, '/ErrorStdOut "' & @ScriptFullPath & '"    ', "")
Global $xCmdLine = _WinAPI_CommandLineToArgv($sCmdLineRaw)
If @error Or ($xCmdLine[0] = 0) Then Exit _WriteLog("! Not enter comnand line!", @ScriptLineNumber)
If $xCmdLine[0] < 2 Then Exit _WriteLog("! You enter not corect comnand line!", @ScriptLineNumber)

Install()

Global $processes = _MyProcessList("MyApp")
If Not @error And IsArray($processes) Then
    If ProcessExists($processes[1]) Then
        _WriteLog("+ App service started succesfully", @ScriptLineNumber)
    EndIf
    _ProcessCloseEx($processes[1])
Else
    _WriteLog("! Your App service not started", @ScriptLineNumber)
EndIf

Func Install()
    Local $hWnd = "MyApp " & $xCmdLine[2] & " Setup"
    Local $installer = "myapp-win-installer-" & $xCmdLine[2] & ".msi"
    If FileExists($installer) Then
        ShellExecute($installer, "", @ScriptDir & "\installers")
        If @error Then
            _WriteLog("Error when starting the installer", @ScriptLineNumber)
            Return
        EndIf
    Else
        Return _WriteLog("Error! installer file not Exists!", @ScriptLineNumber)
    EndIf
    While (Not ControlCommand($hWnd, "", "[Text:&Next >]", "IsEnabled", ''))
        Sleep(500)
        If ControlGetText($hWnd, "", "[Text:Remove Installation]") Then
            _WriteLog("Error: MyApp is already installed", @ScriptLineNumber)
            Sleep(1000)
            WinClose($hWnd)
            Return
        EndIf
    WEnd
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Local $counter = 0
    For $counter = 0 To 1
        Send("{TAB}")
        Sleep(100)
    Next
    Send("{UP}")
    Sleep(100)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:5]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    If WinExists($hWnd, "Port Conflict Found") Then
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:4]")
        Sleep(500)
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    EndIf
    WinWaitActive("MyApp Test")
    ControlClick("MyApp Test", "", "[CLASS:Button; INSTANCE:1]")
    Local $var
    While 1
        $var = ControlGetText($hWnd, "", "[Text:&Finish]")
        If $var == "&Finish" Then
            ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
            ExitLoop
        EndIf
        Sleep(1000)
    WEnd
EndFunc   ;==>Install
Func _ProcessCloseEx($sPID)
    If IsString($sPID) Then $sPID = ProcessExists($sPID)
    If Not $sPID Then Return SetError(1, 0, 0)
    Return Run(@ComSpec & " /c taskkill /F /PID " & $sPID & " /T", @SystemDir, @SW_HIDE)
EndFunc   ;==>_ProcessCloseEx
Func _MyProcessList($str)
    Local $alist = ProcessList(), $ret
    If $alist[0][0] <> 0 Then
        For $1 = 0 To UBound($alist) - 1
            If StringInStr($alist[$1][0], $str) Then $ret &= $alist[$1][0] & '|'
        Next
        Return StringSplit(StringTrimRight($ret, 1), '|')
    EndIf
    Return SetError(1, 0, "")
EndFunc   ;==>_MyProcessList
;
Func _WinAPI_GetString($pString, $bUnicode = True)
    Local $iLength = _WinAPI_StrLen($pString, $bUnicode)
    If @error Or Not $iLength Then Return SetError(@error + 10, @extended, '')
    Local $tString = DllStructCreate(__Iif($bUnicode, 'wchar', 'char') & '[' & ($iLength + 1) & ']', $pString)
    If @error Then Return SetError(@error, @extended, '')
    Return SetExtended($iLength, DllStructGetData($tString, 1))
EndFunc   ;==>_WinAPI_GetString
Func _WinAPI_StrLen($pString, $bUnicode = True)
    Local $W = ''
    If $bUnicode Then $W = 'W'
    Local $aRet = DllCall('kernel32.dll', 'int', 'lstrlen' & $W, 'struct*', $pString)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>_WinAPI_StrLen
Func __Iif($bTest, $vTrue, $vFalse)
    Return $bTest ? $vTrue : $vFalse
EndFunc   ;==>__Iif
Func _WinAPI_CommandLineToArgv($sCmd)
    Local $aResult[1] = [0]
    $sCmd = StringStripWS($sCmd, 1 + 2)
    If Not $sCmd Then
        Return $aResult
    EndIf
    Local $aRet = DllCall('shell32.dll', 'ptr', 'CommandLineToArgvW', 'wstr', $sCmd, 'int*', 0)
    If @error Or Not $aRet[0] Or (Not $aRet[2]) Then Return SetError(@error + 10, @extended, 0)
    Local $tPtr = DllStructCreate('ptr[' & $aRet[2] & ']', $aRet[0])
    Dim $aResult[$aRet[2] + 1] = [$aRet[2]]
    For $i = 1 To $aRet[2]
        $aResult[$i] = _WinAPI_GetString(DllStructGetData($tPtr, 1, $i))
    Next
    DllCall("kernel32.dll", "handle", "LocalFree", "handle", $aRet[0])
    Return $aResult
EndFunc   ;==>_WinAPI_CommandLineToArgv
Func _WriteLog($iLine, $sLine = "")
    Local $iTime = ($sLine == "") ? @HOUR & @MIN & @SEC & ": " & $iLine : @HOUR & @MIN & @SEC & "_ScriptLine-" & $sLine & ": " & $iLine
    FileWriteLine(@ScriptName & ".log", $iTime)
    ConsoleWrite($iTime & @CRLF)
    MsgBox(48 + 262144, "Debug", $iLine & @CRLF & "This Notice On Line: " & $sLine)
EndFunc   ;==>_WriteLog


 


Regards,
 

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

1 hour ago, Trong said:

Bad script:

#RequireAdmin
Opt("TrayAutoPause", 0)
Opt("WinTitleMatchMode", 2)


Global $sCmdLineRaw = @Compiled ? $CmdLineRaw : "" ;StringReplace($CmdLineRaw, '/ErrorStdOut "' & @ScriptFullPath & '"    ', "")
Global $xCmdLine = _WinAPI_CommandLineToArgv($sCmdLineRaw)
If @error Or ($xCmdLine[0] = 0) Then Exit _WriteLog("! Not enter comnand line!", @ScriptLineNumber)
If $xCmdLine[0] < 2 Then Exit _WriteLog("! You enter not corect comnand line!", @ScriptLineNumber)

Install()

Global $processes = _MyProcessList("MyApp")
If Not @error And IsArray($processes) Then
    If ProcessExists($processes[1]) Then
        _WriteLog("+ App service started succesfully", @ScriptLineNumber)
    EndIf
    _ProcessCloseEx($processes[1])
Else
    _WriteLog("! Your App service not started", @ScriptLineNumber)
EndIf

Func Install()
    Local $hWnd = "MyApp " & $xCmdLine[2] & " Setup"
    Local $installer = "myapp-win-installer-" & $xCmdLine[2] & ".msi"
    If FileExists($installer) Then
        ShellExecute($installer, "", @ScriptDir & "\installers")
        If @error Then
            _WriteLog("Error when starting the installer", @ScriptLineNumber)
            Return
        EndIf
    Else
        Return _WriteLog("Error! installer file not Exists!", @ScriptLineNumber)
    EndIf
    While (Not ControlCommand($hWnd, "", "[Text:&Next >]", "IsEnabled", ''))
        Sleep(500)
        If ControlGetText($hWnd, "", "[Text:Remove Installation]") Then
            _WriteLog("Error: MyApp is already installed", @ScriptLineNumber)
            Sleep(1000)
            WinClose($hWnd)
            Return
        EndIf
    WEnd
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Local $counter = 0
    For $counter = 0 To 1
        Send("{TAB}")
        Sleep(100)
    Next
    Send("{UP}")
    Sleep(100)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:5]")
    Sleep(500)
    ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    Sleep(500)
    If WinExists($hWnd, "Port Conflict Found") Then
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:4]")
        Sleep(500)
        ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
    EndIf
    WinWaitActive("MyApp Test")
    ControlClick("MyApp Test", "", "[CLASS:Button; INSTANCE:1]")
    Local $var
    While 1
        $var = ControlGetText($hWnd, "", "[Text:&Finish]")
        If $var == "&Finish" Then
            ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]")
            ExitLoop
        EndIf
        Sleep(1000)
    WEnd
EndFunc   ;==>Install
Func _ProcessCloseEx($sPID)
    If IsString($sPID) Then $sPID = ProcessExists($sPID)
    If Not $sPID Then Return SetError(1, 0, 0)
    Return Run(@ComSpec & " /c taskkill /F /PID " & $sPID & " /T", @SystemDir, @SW_HIDE)
EndFunc   ;==>_ProcessCloseEx
Func _MyProcessList($str)
    Local $alist = ProcessList(), $ret
    If $alist[0][0] <> 0 Then
        For $1 = 0 To UBound($alist) - 1
            If StringInStr($alist[$1][0], $str) Then $ret &= $alist[$1][0] & '|'
        Next
        Return StringSplit(StringTrimRight($ret, 1), '|')
    EndIf
    Return SetError(1, 0, "")
EndFunc   ;==>_MyProcessList
;
Func _WinAPI_GetString($pString, $bUnicode = True)
    Local $iLength = _WinAPI_StrLen($pString, $bUnicode)
    If @error Or Not $iLength Then Return SetError(@error + 10, @extended, '')
    Local $tString = DllStructCreate(__Iif($bUnicode, 'wchar', 'char') & '[' & ($iLength + 1) & ']', $pString)
    If @error Then Return SetError(@error, @extended, '')
    Return SetExtended($iLength, DllStructGetData($tString, 1))
EndFunc   ;==>_WinAPI_GetString
Func _WinAPI_StrLen($pString, $bUnicode = True)
    Local $W = ''
    If $bUnicode Then $W = 'W'
    Local $aRet = DllCall('kernel32.dll', 'int', 'lstrlen' & $W, 'struct*', $pString)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>_WinAPI_StrLen
Func __Iif($bTest, $vTrue, $vFalse)
    Return $bTest ? $vTrue : $vFalse
EndFunc   ;==>__Iif
Func _WinAPI_CommandLineToArgv($sCmd)
    Local $aResult[1] = [0]
    $sCmd = StringStripWS($sCmd, 1 + 2)
    If Not $sCmd Then
        Return $aResult
    EndIf
    Local $aRet = DllCall('shell32.dll', 'ptr', 'CommandLineToArgvW', 'wstr', $sCmd, 'int*', 0)
    If @error Or Not $aRet[0] Or (Not $aRet[2]) Then Return SetError(@error + 10, @extended, 0)
    Local $tPtr = DllStructCreate('ptr[' & $aRet[2] & ']', $aRet[0])
    Dim $aResult[$aRet[2] + 1] = [$aRet[2]]
    For $i = 1 To $aRet[2]
        $aResult[$i] = _WinAPI_GetString(DllStructGetData($tPtr, 1, $i))
    Next
    DllCall("kernel32.dll", "handle", "LocalFree", "handle", $aRet[0])
    Return $aResult
EndFunc   ;==>_WinAPI_CommandLineToArgv
Func _WriteLog($iLine, $sLine = "")
    Local $iTime = ($sLine == "") ? @HOUR & @MIN & @SEC & ": " & $iLine : @HOUR & @MIN & @SEC & "_ScriptLine-" & $sLine & ": " & $iLine
    FileWriteLine(@ScriptName & ".log", $iTime)
    ConsoleWrite($iTime & @CRLF)
    MsgBox(48 + 262144, "Debug", $iLine & @CRLF & "This Notice On Line: " & $sLine)
EndFunc   ;==>_WriteLog


 

Ok, so using the script above, I get the following error, no matter what:

175628_ScriptLine-8: ! Not enter comnand line!

I'm not really sure if this is correct, xCmdLine[0] can't be 0 no matter what, as far as I get how things work with command line parameters.

 

Also, 

2 hours ago, Jos said:

.... and?

Did you get the console prompt? ( Maybe you need to change that to a MSGBOX() so it always shows!
You really need to learn to start providing information and help testing when you want your issue to be resolved! ;)

Try replacing that added test with this version:

Global $defaultLocation = "C:\Program Files\MyApp\" & $CmdLine
Global $sCmdLine = _WinAPI_CommandLineToArgv($CmdLineRaw)
if UBound($sCmdLine) < 3 then
    MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @CRLF & '$CmdLineRaw' & @CRLF & @CRLF & 'Return:' & @CRLF & $CmdLineRaw)
    Exit
EndIf

The script will exit after showing the msgbox() in case there are not enough parameters provided.

Jos

when using the above code, the script works fine when running the .au3 with the parameter, but the MsgBox pops when launching the .exe.

 

Untitled1.png

Edited by mihaijulien

Share this post


Link to post
Share on other sites

#19 ·  Posted

Yes of course it will popup!
I am have given you the appropriate information to resolve your problem and the ball is in your corner to do something with that provided information.
Let me know when you have questions.

Jos


Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#20 ·  Posted

7 minutes ago, mihaijulien said:

Ok, so using the script above, I get the following error, no matter what:

175628_ScriptLine-8: ! Not enter comnand line!

I'm not really sure if this is correct, xCmdLine[0] can't be 0 no matter what, as far as I get how things work with command line parameters.

 

 

You did not understand your code and how it works!
Code works very well, only humans write wrong code and making it not work!

You have run the file directly and do not have any command passed on it!
Your code need to get the command parameters and work on it!

Do you still want the code to work for you? with no command line?


Regards,
 

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

    • hcI
      By hcI
      Hello I would like to know if there is a way to return a sentence in cmd when I launch from it (because I add arguments).
      For example, diskpart.exe which help to manage the key and hdd connected, when you launch it with the parameter "/f" the app return a sentence saying that it don't recognize the parameter "/f" and it return the sentence in the cmd where i started the application, not a new one.
      That's what I want to do but I couldn't find anything that would solve my problem on internet and on AutoIt like ConsoleWrite / ConsoleWriteError (don't work).
       
      Thanks
    • Duck
      By Duck
      I'm attempting to capture the output from the command line tool PSEXEC. I'm using AutoIT to run an instance of PSEXEC against a remote PC to audit Local Admins in my environment using net.exe (C:\Windows\System32> net localgroup administrators). However the usual trick I use to capture command line output does not appear to work well with PSEXEC, as the bottom portion of the output is missing from the return. Any ideas or recommendations are greatly appreciated.  
       
      Here is what I'm working with: 
      ;This script will read from a list of hosts and report who has local admin privileges on the machine #RequireAdmin Global $fileName = @ScriptDir & '\test.txt' ;hostlist, one host per line readHostList() ;Read list of hosts Func readHostList() Local $file = FileOpen($fileName, 0) While 1 $line = FileReadLine($file) If @error = -1 Then ExitLoop ConsoleWrite($line & @CRLF) ;MsgBox(0,0,$line) getLocalAdmins($line) WEnd FileClose($file) EndFunc ;run PSEXEC to list local admins Func getLocalAdmins($remotePC) Local $testFile = @ScriptDir &'\test234.txt' FileOpen($testFile, 1) Local $psexec = 'psexec \\' & $remotePC & ' net localgroup administrators' FileWriteLine($testFile, _RunCmd($psexec) ) FileClose($testFile) EndFunc ;Used to return CLI output Func _RunCmd($sCommand) Local $nPid = Run(@Comspec & " /c" & $sCommand, @SystemDir, @SW_Hide, 8), $sRet = "" If @Error then Return "ERROR:" & @ERROR ProcessWait($nPid) While 1 $sRet &= StdoutRead($nPID) If @error Or (Not ProcessExists ($nPid)) Then ExitLoop WEnd Return $sRet EndFunc  
      ## If i manually run the command on the remote PC via PSEXEC I will get the following output: 
      PsExec v2.11 - Execute processes remotely
      Copyright (C) 2001-2014 Mark Russinovich
      Sysinternals - www.sysinternals.com
      Starting net on PCNAME... on PCNAME...
      net exited on PCNAME with error code 0.
      -------------------------------------------------------------------------------
      admin
      Administrator
      Alias name     administrators
      Domain\Domain Admins
      Comment        Administrators have complete and unrestricted access to the computer/domain
      Members
      The command completed successfully.
       
      ## The returned output from running the above script is as follows:
      PsExec v2.11 - Execute processes remotely
      Copyright (C) 2001-2014 Mark Russinovich
      Sysinternals - www.sysinternals.com
      Alias name     administrators
      Connecting to PCNAME...
      Starting PSEXESVC service on PCNAME...
      Connecting with PsExec service on PCName...
      Starting net on PCNAME..
      net exited on PCNAME with error code 0.
       
      **Note to test this script PSEXEC must be in the system dir or the path in the script changed 
      PSEXEC tool: https://docs.microsoft.com/en-us/sysinternals/downloads/psexec
    • luckyluke
      By luckyluke
      Hello,
      Im trying to read the output from CMD using Dllcall, here is my code:
      #include <WinAPI.au3> #include <array.au3> Global Const $STD_OUTPUT_HANDLE = -11 Global Const $_CONSOLE_SCREEN_BUFFER_INFO = _ "struct;int dwSizeX;" & _ "short dwSizeY;" & _ "short dwCursorPositionX;" & _ "short dwCursorPositionY;" & _ "short wAttributes;" & _ "short Left;" & _ "short Top;" & _ "short Right;" & _ "short Bottom;" & _ "short dwMaximumWindowSizeX;" & _ "short dwMaximumWindowSizeY;endstruct" $pCmd = Run( "cmd.exe" ) Sleep(1000) $hCmd = WinGetHandle("") ConsoleWrite('handle:' & $hCmd & @CRLF) $aRet = DllCall("kernel32.dll", "int", "AttachConsole", "dword", $pCmd) ;_ArrayDisplay($aRet) If $aRet[0] <> 0 Then $vHandle_data='' $vHandle='' $vHandle_data = DllStructCreate($_CONSOLE_SCREEN_BUFFER_INFO) ; Screen Buffer structure $aRet1 = DllCall("kernel32.dll", "hwnd", "GetStdHandle", "dword", $STD_OUTPUT_HANDLE) if not @error Then $vHandle = $aRet1[0] $aRet = DllCall("kernel32.dll", "int", "GetConsoleScreenBufferInfo", "hwnd", $vHandle, _ "ptr", $vHandle_data) MsgBox(0, '1',DllStructGetData($vHandle_data, 'dwSizeX') & _WinAPI_GetLastErrorMessage()) EndIf It did not work, i got the message 'The handle is invalid'. Please help?
      Thank you in advance!
    • fosil
      By fosil
      Hi everyone.

      I'm currently working a program that constantly prints out log files through "consolewrite" and the "#AutoIt3Wrapper_Change2CUI=y" wrapper.

      Part of this program requires me to run a batch script.

      My issue is the batch script launches from the same window as consolewrite. I need the batch file to be launched through a different window as currently this causes an issue with the logs (which need to be very precise) but also causes the batch file to produce some funny behavior...

      Does anyone know how I can force the file to run on a second DOS window?

      Thanks in advance!!!
       
      Edit: Im using the "run" command if that helps. I tried "shellexecute" but that seemed to not launch the batch scripts at all.
    • Baboo85
      By Baboo85
      Hi all,
      I need to start a script that include:
      - admin privileges
      - multiple cmd commands
      - no bat, no exe, no tmp files created anywhere (especially in the user temp folder)
      In a bat file it would be simple, but users shouldn't see what commands I'm sending.
      Example of the script:
      echo off cls echo. echo I AM A TOOL echo. echo NOTE: echo - note 1 echo - note 2 echo - etc set USER1=0 set COMPUTER1=0 if /i %username% equ user.user ( set USER1=1 set COMPUTER1=1 ) if /i %username% equ another.user set USER1=1 if /i %computername% equ notebook set COMPUTER1=1 if %USER1% EQU 1 ( if %COMPUTER1% EQU 1 ( reg delete "HKLM\SOFTWARE\blablabla" /f ) else ( echo Computer not authorized. Contact assistance.) ) else ( echo User not authorized. Contact assistance.) echo. pause exit With the send("") is a disaster.
      I'm a noob here, so what can I do?
       
      EDIT: OR ELSE I explain the situation and what I need, so if there is a simple solution I can use that.
       
      SITUATION: our domain users have Users rights on the machine. Some of them need administrator rights.
      We create a local user with administrator rights, so that the users must insert username and password when asked to run something with administrator rights.
      We have an internal domain group policy that blocks EXE, BAT, COM, TMP files from the user local temp directory, for a security reason (malware). That also blocks most software installation.
      But some users are often out of office, away from workplace and in another country, they need a complete control on their computers.
       
      WHAT I NEED: I need to check the username and the computer name. If the username is the one with local administrator rights and the computer name is a computer that is qualified to temporary remove the policy, then I need to execute a REG DELETE command with administrator rights.
       
      I hope I explained myself.
       
      Thank you very much.