Jump to content

I can't close my command_line script


Luigi
 Share

Recommended Posts

Greetings,

I create this script to practice how write and get input/output from MS-DOS, SQLPlus, PLink, etc...

Now, its work fine...

But with my script "command_line.exe", I cant close/kill the process.

Of course, if I type "exit", ok, the PID is closes, but, there are another smart way?

 

Best regards,

automacao.au3

; #UDF# =========================================================================================================================
; Name...........: automacao.au3
; Description ...: terminal para automacao de script de linha de comando
; Exemplo........:
; Author ........: Luigi (Luismar Chechelaky)
; Link ..........: https://github.com/chechelaky/WMI/CIM_Display.au3
; AutoIt version.: 3.3.14.2
; ===============================================================================================================================

;~ #AutoIt3Wrapper_AU3Check_Parameters= -q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
;~ #Tidy_Parameters=/sf

; Autor: Luigi
; Agradecimentos:
;   @Elias (http://forum.autoitbrasil.com/index.php?/user/1384-elias/)
;   http://forum.autoitbrasil.com/index.php?/topic/1121-runstdio-executa-um-programa-dos-e-retorna-a-saida-da-console/#entry13419

#include-once
#include <Array.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiEdit.au3>
#include <ScrollBarsConstants.au3>

OnAutoItExitRegister("OnExit")

Opt("GUIOnEventMode", 1)
Opt("GUIEventOptions", 1)
Opt("MustDeclareVars", 1)

Global $PID_RUN = False
Global $aGuiSize[2] = [800, 600]
Global $sGuiTitle = "PID[ 0 ]"
Global $hGui
Global $hOutput, $hInput
Global $buffer, $read

$hGui = GUICreate($sGuiTitle, $aGuiSize[0], $aGuiSize[1])
GUISetFont(9, 400, 0, "DOSLike", $hGui)
GUISetOnEvent($GUI_EVENT_CLOSE, "Quit")
$hOutput = GUICtrlCreateEdit("", 10, 10, $aGuiSize[0] - 20, $aGuiSize[1] - 200, $WS_VSCROLL + $ES_AUTOVSCROLL + $ES_READONLY)
$hInput = GUICtrlCreateInput("", 10, $aGuiSize[1] - 200 + 20, $aGuiSize[0] - 20, 170)

GUISetState(@SW_SHOW, $hGui)


Global $PID = COMMAND_LINE()
;~ Global $PID = DOS()
;~ Run(@ComSpec & " /c cmd.exe", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)

WinSetTitle($hGui, "", "PID[" & $PID & "]")
Global $aa = "", $bb = ""

GUIRegisterMsg($WM_ACTIVATE, "WM_ACTIVATE")
GUICtrlSetState($hInput, $GUI_FOCUS)
HotKeySet("{ENTER}", "Enter")

While Sleep(10)
    If ProcessExists($PID) And $PID_RUN Then
        $aa = StdoutRead($PID, False, False)
        If $aa Then
            Output("$aa: " & $aa)
            $aa = ""
        EndIf
        $bb = StderrRead($PID, False, True)
        If $bb Then
            $bb = BinaryToString($bb)
            Output("$bb: " & $bb)
            $bb = ""
        EndIf
    ElseIf Not ProcessExists($PID) And $PID_RUN Then
        $PID_RUN = False
        WinSetTitle($hGui, "", "PID[ 0 ]")
    ElseIf ProcessExists($PID) And Not $PID_RUN Then
        $PID_RUN = True
        WinSetTitle($hGui, "", "PID[ " & $PID & " ]")
    EndIf
WEnd

Func COMMAND_LINE()
    $PID = Run(@ComSpec & " /c command_line.exe", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
    If @error Then Return SetError(1, 0, 0)
    $PID_RUN = True
    Return $PID
EndFunc   ;==>COMMAND_LINE

Func DOS()
    Local $PID = Run(@ComSpec & " /c cmd.exe", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
    If @error Then Return SetError(1, 0, 0)
    $PID_RUN = True
    Return $PID
EndFunc   ;==>DOS

Func WM_ACTIVATE($hWnd, $Msg, $wParam, $lParam)
    If BitAND($wParam, 0xFFFF) Then
        HotKeySet("{ENTER}", "Enter")
    Else
        HotKeySet("{ENTER}")
    EndIf
EndFunc   ;==>WM_ACTIVATE

Func Enter()
    Local $input = GUICtrlRead($hInput)
    $input = StringRegExpReplace($input, "[\r\n]", "")
    If $input Then GUICtrlSetData($hInput, "")
    Local $num = StdinWrite($PID, $input & @CRLF)
;~  Output($input)
EndFunc   ;==>Enter

Func Output($input = "")
;~  https://unix.stackexchange.com/questions/208436/bell-and-escape-character-in-prompt-string
;~ ESC \
;~      String Terminator (ST  is 0x9c).
;~ ESC ]
;~      Operating System Command (OSC  is 0x9d).
;~  0 - ANSI code page
;~  1 - OEM code page
;~  2 - Macintosh code page
;~  3 - The Windows ANSI code page for the current thread
;~  42 - Symbol code page
;~  850
;~  65000 - UTF-7
;~  65001 - UTF-8
    $input = _WinAPI_MultiByteToWideChar($input, 850, 0, True)
    Trim($input)
    If Not $input Then Return
    ConsoleWrite($input & @LF)
    Local $output = GUICtrlRead($hOutput)
    Trim($output)
    GUICtrlSetData($hOutput, $output & @CRLF & $input)
    _GUICtrlEdit_Scroll($hOutput, $SB_SCROLLCARET)
EndFunc   ;==>Output

Func PID_Close()
    ConsoleWrite("PID_Close()" & @LF)
    If Not $PID Then Return
    StdinWrite($PID, "!{F4}" & @CRLF)
    StdinWrite($PID, "^c" & @CRLF)

    Local $try
    While $PID
        $try = ProcessClose($PID)
        ConsoleWrite("try[" & $try & "] $PID[" & $PID & "] @error[" & @error & "]" & @LF)
        Sleep(100)
    WEnd
EndFunc   ;==>PID_Close

Func OnExit()
    PID_Close()
    GUISetState($hGui, @SW_HIDE)
    GUIDelete($hGui)
EndFunc   ;==>OnExit

Func Quit()
    Exit
EndFunc   ;==>Quit

Func Trim(ByRef $str)
    While StringLeft($str, 1) = @CRLF Or StringLeft($str, 1) = @LF Or StringLeft($str, 1) = @CR
        $str = StringTrimLeft($str, 1)
    WEnd

    While StringRight($str, 1) = @CRLF Or StringRight($str, 1) = @LF Or StringRight($str, 1) = @CR
        $str = StringTrimRight($str, 1)
    WEnd
EndFunc   ;==>Trim

command_line.au3  (compile command_line before use)

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=command_line.exe
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Fileversion=0.0.0.4
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_Language=1046
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
; #UDF# =========================================================================================================================
; Name...........: command_line.exe
; Description ...: script de linha de comando
; Exemplo........:
; Author ........: Luigi (Luismar Chechelaky)
; Link ..........: https://github.com/chechelaky/GitHub/blob/master/AutoIt/AutomacaoConsole/command_line.au3
; AutoIt version.: 3.3.14.2
; ===============================================================================================================================
#include-once
#include <FileConstants.au3>
#include <String.au3>


Global $VERSION = FILE_VERSION()
ConsoleWrite(@ScriptName & " Version:" & $VERSION & @CRLF)
ConsoleWrite("by Luigi" & @CRLF)

If $cmdline[0] Then
    ConsoleWrite("$iParam= " & $cmdline[0] & @CRLF)
Else
    ConsoleWrite("$iParam= 0" & @CRLF)
EndIf

Global $read = ""

While Sleep(10)
    $read = ConsoleRead()
    If $read Then Executa(StringRegExpReplace($read, "[\r\n]", ""))
WEnd

Func Executa($input)
    Switch StringLower($input)
        Case 1
            Retorno("um", 2)
        Case 2
            Retorno("dois", 2)
        Case 3
            Retorno("tres", 2)
        Case 4
            Retorno("quatro", 2)
        Case 5
            Retorno("cincod", 2)
        Case 6
            Retorno("seis", 2)
        Case 7
            Retorno("sete", 2)
        Case 8
            Retorno("oito", 2)
        Case 9
            Retorno("nove", 2)
        Case "exit", "quit", "bye"
            Quit()
        Case Else
            Retorno("unknow command <" & $input & ">", 1)
    EndSwitch
EndFunc   ;==>Executa

Func Retorno($input, $mode = 0)
    Switch $mode
        Case 0
            Local $num = Random(0, 999, 1)
            Sleep($num)
            ConsoleWrite(">Ok: " & $input & " $num[ " & $num & " ]" & @CRLF)
        Case 1
            Local $num = Random(1000, 1999, 1)
            Sleep($num)
            ConsoleWriteError(">Error: " & $input & " $num[ " & $num & " ]" & @CRLF)
        Case Else
            Retorno($input, Random(0, 1, 1))
    EndSwitch
EndFunc   ;==>Retorno

Func Quit()
    Retorno("Exit", 0)
    Exit
EndFunc   ;==>Quit

Func FILE_VERSION()
    If @Compiled Then
        Return FileGetVersion(@ScriptFullPath, $FV_FILEVERSION)
    Else
        Local $hFile = FileOpen(@ScriptFullPath, 0)
        Local $read = FileRead($hFile)
        FileClose($read)
        Local $arr = _StringBetween($read, "#AutoIt3Wrapper_Res_Fileversion=", @CRLF)
        If IsArray($arr) And $arr[0] Then Return $arr[0]
        Return "0.0.0.0"
    EndIf
EndFunc   ;==>FILE_VERSION

 

Visit my repository

Link to comment
Share on other sites

  • Developers
1 hour ago, Luigi said:

If ProcessExists($PID) And $PID_RUN Then

What are these tests supposed to test for? Whether $PID and $PID_RUN processes exists?
If so then your statement is obviously wrong as the second part of the test is not testing for ProcessExists().

Jos

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

Link to comment
Share on other sites

@Jos, thanks for you reply.

The code its work without $PID_RUN.
Why I use?

In my understanding, with each loop, the code will rewrite WinTitle.

$PID_RUN saves the $PID state change and prevents WinSetTitle from each loop, updating only when necessary.

I see update a variables's value is easy than update a WinSetTitle.

This is something I've learned to use with GDI, maybe it's a bad smell in the code. No one has confronted me until today.

In my college, we call bad smell as "worst practices" in the code.

Edited by Luigi

Visit my repository

Link to comment
Share on other sites

The mistake is in PID_Close() loop:

While $PID
        $try = ProcessClose($PID)
        ConsoleWrite("try[" & $try & "] $PID[" & $PID & "] @error[" & @error & "]" & @LF)
        Sleep(100)
    WEnd

There is nothing in that loop that changes $PID variable, therefore it get stuck in infinite loop.

You probably want change it to:

While ProcessExists($PID)
        $try = ProcessClose($PID)
        ConsoleWrite("try[" & $try & "] $PID[" & $PID & "] @error[" & @error & "]" & @LF)
        Sleep(100)
    WEnd

 

Edited by VAN0
Link to comment
Share on other sites

 

_ProcessCloseTree("Application.exe")


Func _ProcessCloseTree($iPID)
    If IsString($iPID) Then $iPID = ProcessExists($iPID) ;To get PID
    If Not $iPID Then Return SetError(1, 0, 0)

    Local $aProc_List = ProcessList()

    For $i = 1 To $aProc_List[0][0]
        If _ProcessGetParent($aProc_List[$i][1]) = $iPID Then ProcessClose($aProc_List[$i][1])
    Next

    ProcessClose($iPID)
EndFunc   ;==>_ProcessCloseTree

Func _ProcessGetParent($iPID)
    Local $wbemFlagReturnImmediately = 0x10
    Local $wbemFlagForwardOnly = 0x20
    Local $colItems = ""
    Local $strComputer = "localhost"

    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    If IsObj($colItems) Then
        For $objItem In $colItems
            If $objItem.ProcessID = $iPID Then Return $objItem.ParentProcessID
        Next
    EndIf

    Return SetError(1, 0, 0)
EndFunc   ;==>_ProcessGetParent

 

Link to comment
Share on other sites

Thanks @VAN0, @aa2zz6, but is curious... does not work!

I can't kill my proccess! kkkk

Func PID_Close()
    ConsoleWrite("PID_Close()" & @LF)
    If Not $PID Then Return
    StdinWrite($PID, "exit" & @CRLF)

    ProcessClose($PID)

EndFunc   ;==>PID_Close

But, this is not generic...

The others .exe, like sqlplus.exe, plink.exe, ms-dos, it's close fine.

Visit my repository

Link to comment
Share on other sites

I found a solution...

Proccess($PID) is not a command_line.exe, $PID is a cmd.exe!

I need found the $PID's command_line.exe, kill first, and the, kill the $PID.

For this, I use $APP_NAME, it was charged when $PID was created.

Func PID_Close()
    ConsoleWrite("PID_Close( $PID=" & $PID & " )" & @LF)
    If Not $PID Then Return
    Local $aProccesList = ProcessList()
    Local $iSearch = _ArraySearch($aProccesList, $APP_NAME, 1, Default, 0, 0, 0, 0)
    If @error Then
        ConsoleWrite("Error to close!" & @LF)
    Else
        ProcessClose($aProccesList[$iSearch][1])
        ProcessClose($PID)
        $APP_NAME = ""
    EndIf
EndFunc   ;==>PID_Close

This way work fine! (o.O)

This is the code:

; #UDF# =========================================================================================================================
; Name...........: automacao.au3
; Description ...: terminal para automacao de script de linha de comando
; Exemplo........:
; Author ........: Luigi (Luismar Chechelaky)
; Link ..........: https://github.com/chechelaky/WMI/CIM_Display.au3
; AutoIt version.: 3.3.14.2
; ===============================================================================================================================

;~ #AutoIt3Wrapper_AU3Check_Parameters= -q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
;~ #Tidy_Parameters=/sf

; Autor: Luigi
; Agradecimentos:
;   @Elias (http://forum.autoitbrasil.com/index.php?/user/1384-elias/)
;   http://forum.autoitbrasil.com/index.php?/topic/1121-runstdio-executa-um-programa-dos-e-retorna-a-saida-da-console/#entry13419

#include-once
#include <Array.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiEdit.au3>
#include <ScrollBarsConstants.au3>

OnAutoItExitRegister("OnExit")

Opt("GUIOnEventMode", 1)
Opt("GUIEventOptions", 1)
Opt("MustDeclareVars", 1)

Global $APP_NAME = ""
Global $PID_RUN = False
Global $aGuiSize[2] = [800, 600]
Global $sGuiTitle = "PID[ 0 ]"
Global $hGui
Global $hOutput, $hInput
Global $buffer, $read

$hGui = GUICreate($sGuiTitle, $aGuiSize[0], $aGuiSize[1])
GUISetFont(9, 400, 0, "DOSLike", $hGui)
GUISetOnEvent($GUI_EVENT_CLOSE, "Quit")
$hOutput = GUICtrlCreateEdit("", 10, 10, $aGuiSize[0] - 20, $aGuiSize[1] - 200, $WS_VSCROLL + $ES_AUTOVSCROLL + $ES_READONLY)
$hInput = GUICtrlCreateInput("", 10, $aGuiSize[1] - 200 + 20, $aGuiSize[0] - 20, 170)

GUISetState(@SW_SHOW, $hGui)


Global $PID = COMMAND_LINE()
;~ Global $PID = DOS()
;~ Run(@ComSpec & " /c cmd.exe", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)

WinSetTitle($hGui, "", "PID[" & $PID & "]")
Global $aa = "", $bb = ""

GUIRegisterMsg($WM_ACTIVATE, "WM_ACTIVATE")
GUICtrlSetState($hInput, $GUI_FOCUS)
HotKeySet("{ENTER}", "Enter")

While Sleep(10)
    If ProcessExists($PID) And $PID_RUN Then
        $aa = StdoutRead($PID, False, False)
        If $aa Then
            Output("$aa: " & $aa)
            $aa = ""
        EndIf
        $bb = StderrRead($PID, False, True)
        If $bb Then
            $bb = BinaryToString($bb)
            Output("$bb: " & $bb)
            $bb = ""
        EndIf
    ElseIf Not ProcessExists($PID) And $PID_RUN Then
        $PID_RUN = False
        WinSetTitle($hGui, "", "PID[ 0 ]")
    ElseIf ProcessExists($PID) And Not $PID_RUN Then
        $PID_RUN = True
        WinSetTitle($hGui, "", "PID[ " & $PID & " ]")
    EndIf
WEnd

Func COMMAND_LINE()
    $APP_NAME = "command_line.exe"
    $PID = Run(@ComSpec & " /c " & $APP_NAME, @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
    If @error Then Return SetError(1, 0, 0)
    $PID_RUN = True
    Return $PID
EndFunc   ;==>COMMAND_LINE

Func DOS()
    $APP_NAME = "cmd.exe"
    $PID = Run(@ComSpec & " /c " & $APP_NAME, @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
    If @error Then Return SetError(1, 0, 0)
    $PID_RUN = True
    Return $PID
EndFunc   ;==>DOS

Func WM_ACTIVATE($hWnd, $Msg, $wParam, $lParam)
    If BitAND($wParam, 0xFFFF) Then
        HotKeySet("{ENTER}", "Enter")
    Else
        HotKeySet("{ENTER}")
    EndIf
EndFunc   ;==>WM_ACTIVATE

Func Enter()
    Local $input = GUICtrlRead($hInput)
    $input = StringRegExpReplace($input, "[\r\n]", "")
    If $input Then GUICtrlSetData($hInput, "")
    Local $num = StdinWrite($PID, $input & @CRLF)
;~  Output($input)
EndFunc   ;==>Enter

Func Output($input = "")
;~  https://unix.stackexchange.com/questions/208436/bell-and-escape-character-in-prompt-string
;~ ESC \
;~      String Terminator (ST  is 0x9c).
;~ ESC ]
;~      Operating System Command (OSC  is 0x9d).
;~  0 - ANSI code page
;~  1 - OEM code page
;~  2 - Macintosh code page
;~  3 - The Windows ANSI code page for the current thread
;~  42 - Symbol code page
;~  850
;~  65000 - UTF-7
;~  65001 - UTF-8
    $input = _WinAPI_MultiByteToWideChar($input, 850, 0, True)
    Trim($input)
    If Not $input Then Return
    ConsoleWrite($input & @LF)
    Local $output = GUICtrlRead($hOutput)
    Trim($output)
    GUICtrlSetData($hOutput, $output & @CRLF & $input)
    _GUICtrlEdit_Scroll($hOutput, $SB_SCROLLCARET)
EndFunc   ;==>Output

Func PID_Close()
    ConsoleWrite("PID_Close( $PID=" & $PID & " )" & @LF)
    If Not $PID Then Return
    Local $aProccesList = ProcessList()
    Local $iSearch = _ArraySearch($aProccesList, $APP_NAME, 1, Default, 0, 0, 0, 0)
    If @error Then
        ConsoleWrite("Error to close!" & @LF)
    Else
        ProcessClose($aProccesList[$iSearch][1])
        ProcessClose($PID)
        $APP_NAME = ""
    EndIf
EndFunc   ;==>PID_Close

Func OnExit()
    PID_Close()
    GUISetState($hGui, @SW_HIDE)
    GUIDelete($hGui)
EndFunc   ;==>OnExit

Func Quit()
    Exit
EndFunc   ;==>Quit

Func Trim(ByRef $str)
    While StringLeft($str, 1) = @CRLF Or StringLeft($str, 1) = @LF Or StringLeft($str, 1) = @CR
        $str = StringTrimLeft($str, 1)
    WEnd

    While StringRight($str, 1) = @CRLF Or StringRight($str, 1) = @LF Or StringRight($str, 1) = @CR
        $str = StringTrimRight($str, 1)
    WEnd
EndFunc   ;==>Trim

 

Visit my repository

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...