Luigi

I can't close my command_line script

7 posts in this topic

#1 ·  Posted

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

Share this post


Link to post
Share on other sites



#2 ·  Posted

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


Visit the SciTE4AutoIt3 Download page for the latest versions  - Beta files                                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

#3 ·  Posted (edited)

@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

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#5 ·  Posted

 

_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

 

Share this post


Link to post
Share on other sites

#6 ·  Posted

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

Share this post


Link to post
Share on other sites

#7 ·  Posted

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

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