Luigi Posted August 26, 2017 Share Posted August 26, 2017 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 expandcollapse popup; #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) expandcollapse popup#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 More sharing options...
Developers Jos Posted August 26, 2017 Developers Share Posted August 26, 2017 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 More sharing options...
Luigi Posted August 26, 2017 Author Share Posted August 26, 2017 (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 August 26, 2017 by Luigi Visit my repository Link to comment Share on other sites More sharing options...
VAN0 Posted August 26, 2017 Share Posted August 26, 2017 (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 August 26, 2017 by VAN0 Link to comment Share on other sites More sharing options...
aa2zz6 Posted August 26, 2017 Share Posted August 26, 2017 _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 More sharing options...
Luigi Posted August 26, 2017 Author Share Posted August 26, 2017 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 More sharing options...
Luigi Posted August 26, 2017 Author Share Posted August 26, 2017 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: expandcollapse popup; #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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now