Dan_555 Posted May 13, 2020 Share Posted May 13, 2020 (edited) Hi, this is not my script. I have used the Autoit Examples\GUI\Advanced\_NamedPipes_Server.au3 script and stripped down everything unneeded. Now it functions like what both Client and Server script did, just in one file: It captures the command-line output directly, using the pipe, and puts it into its own edit field. expandcollapse popup#include <GuiStatusBar.au3> #include <GuiEdit.au3> #include <GuiConstantsEx.au3> #include <NamedPipes.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ; =============================================================================================================================== ; Description ...: This was the server side of the pipe demo ; Author ........: Paul Campbell (PaulIA) ; Notes .........: CMD-Mod by dan_555 ; =============================================================================================================================== ; =============================================================================================================================== ; Global constants ; =============================================================================================================================== Global Const $BUFSIZE = 1024 * 4 Global Const $PIPE_NAME = "\\.\\pipe\\AutoIt3PipeTest" Global Const $TIMEOUT = 5000 Global Const $WAIT_TIMEOUT = 250 Global Const $ERROR_IO_PENDING = 997 Global Const $ERROR_PIPE_CONNECTED = 535 Global $locktimer = 0, $lockexit = 0, $inp1Txt Global $h_PID = 0 Global $closingdelay = 1000, $closecounter = 0, $TimeHandle = TimerInit(), $TimeDiff = TimerDiff($TimeHandle) ;Used for CloseGuiOnDoubleClick() Global $formTitle = "Pipe CMD Test" ; =============================================================================================================================== ; Global variables ; =============================================================================================================================== Global $g_hEvent, $g_idMemo, $g_pOverlap, $g_tOverlap, $g_hPipe, $g_hReadPipe, $g_iState, $g_iToWrite ; =============================================================================================================================== ; Main ; =============================================================================================================================== GUIRegisterMsg($WM_SIZE, "WM_SIZE") CreateGUI() InitPipe() MsgLoop() ; =============================================================================================================================== ; Creates a GUI ; =============================================================================================================================== Func CreateGUI() Global $hGUI = GUICreate($formTitle, 500, 400, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX, $WS_THICKFRAME)) Global $Button1 = GUICtrlCreateButton("Go", 2, 1, 37, 29) GUICtrlSetTip(-1, "Execute the command from the input box") Global $StatusBar1 = _GUICtrlStatusBar_Create($hGUI) Global $g_idMemo = GUICtrlCreateEdit("", 0, 31, 499, 349) Global $Input1 = GUICtrlCreateInput("", 40, 4, 380, 24) GUICtrlSetTip(-1, "Command to execute. Enter to start!" & @CRLF & "Needs user input to accept enter key!") Global $Button2 = GUICtrlCreateButton("CLS", 421, 1, 30, 29) GUICtrlSetTip(-1, "Clear the output") Global $Button3 = GUICtrlCreateButton("STOP", 461, 1, 35, 29) GUICtrlSetTip(-1, "Emergency stop, works only if a command is running." & @CRLF & "This will close the running Proccess !!!") GUICtrlSetFont($g_idMemo, 9, 400, 0, "Courier New") GUISetState() GUICtrlSetLimit($g_idMemo, 555555555) GuiCtrlSetState ($Button3,$GUI_DISABLE) EndFunc ;==>CreateGUI ; =============================================================================================================================== ; This function creates an instance of a named pipe ; =============================================================================================================================== Func InitPipe() ; Create an event object for the instance $g_tOverlap = DllStructCreate($tagOVERLAPPED) $g_pOverlap = DllStructGetPtr($g_tOverlap) $g_hEvent = _WinAPI_CreateEvent() If $g_hEvent = 0 Then LogMSG("ERR:InitPipe ..........: API_CreateEvent failed") Return EndIf DllStructSetData($g_tOverlap, "hEvent", $g_hEvent) ; Create a named pipe $g_hPipe = _NamedPipes_CreateNamedPipe($PIPE_NAME, _ ; Pipe name 2, _ ; The pipe is bi-directional 2, _ ; Overlapped mode is enabled 0, _ ; No security ACL flags 1, _ ; Data is written to the pipe as a stream of messages 1, _ ; Data is read from the pipe as a stream of messages 0, _ ; Blocking mode is enabled 1, _ ; Maximum number of instances $BUFSIZE, _ ; Output buffer size $BUFSIZE, _ ; Input buffer size $TIMEOUT, _ ; Client time out 0) ; Default security attributes If $g_hPipe = -1 Then LogMSG("ERR:InitPipe ..........: _NamedPipes_CreateNamedPipe failed") EndIf EndFunc ;==>InitPipe ; =============================================================================================================================== ; This function loops, waiting for user input or the GUI to close ; =============================================================================================================================== Func MsgLoop() GUICtrlSetData ($Input1,"cmd.exe /c dir C:\ /oN") While 1 CloseGuiOnDoubleClick("loop") $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE CloseGuiOnDoubleClick("button") Case $Input1 Go() Case $Button1 ;Execute the command from the edit field Go() Case $Button2 ;Clear the Edit field MemoWrite("", 1) EndSwitch WEnd EndFunc ;==>MsgLoop Func Go() $inp1Txt = GUICtrlRead($Input1) If $inp1Txt <> "" Then If ExecuteCmd($inp1Txt) Then GuiCtrlSetState ($Button3,$GUI_ENABLE) While $lockexit = 0 ;Exits the loop when the ReadOutput() stops receiving data. If GUIGetMsg() = $Button3 Then ProcessClose($h_PID) ;Stop Button, closes the proccess id - in case it is stuck _GUICtrlEdit_BeginUpdate($g_idMemo) ;This allows the edit field to be scrolled via scrollbars, while getting data. ReadOutput() ;Read the pipe and set the output into the edit field _GUICtrlEdit_EndUpdate($g_idMemo) WEnd $lockexit = 0 GuiCtrlSetState ($Button3,$GUI_DISABLE) LogMsg("done") EndIf EndIf EndFunc ;==>Go Func ReadOutput() Local $pBuffer, $tBuffer, $sLine, $iRead, $bSuccess, $iWritten $tBuffer = DllStructCreate("char Text[" & $BUFSIZE & "]") $pBuffer = DllStructGetPtr($tBuffer) ; Read data from console pipe _WinAPI_ReadFile($g_hReadPipe, $pBuffer, $BUFSIZE, $iRead) If $iRead = 0 Then _WinAPI_CloseHandle($g_hReadPipe) _WinAPI_FlushFileBuffers($g_hPipe) $lockexit = 1 $h_PID = 0 Return EndIf ; Get the data and strip out the extra carriage returns $sLine = StringLeft(DllStructGetData($tBuffer, "Text"), $iRead) $sLine = StringReplace($sLine, @CR & @CR, @CR) If $sLine <> "" Then MemoWrite($sLine) EndFunc ;==>ReadOutput ; =============================================================================================================================== ; Executes a command and returns the results ; =============================================================================================================================== Func ExecuteCmd($sCmd) Local $tProcess, $tSecurity, $tStartup, $hWritePipe ; Set up security attributes $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) DllStructSetData($tSecurity, "InheritHandle", True) ; Create a pipe for the child process's STDOUT If Not _NamedPipes_CreatePipe($g_hReadPipe, $hWritePipe, $tSecurity) Then LogMSG("ERR: ExecuteCmd ........: _NamedPipes_CreatePipe failed") Return False EndIf ; Create child process $tProcess = DllStructCreate($tagPROCESS_INFORMATION) $tStartup = DllStructCreate($tagSTARTUPINFO) DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW)) DllStructSetData($tStartup, "StdOutput", $hWritePipe) DllStructSetData($tStartup, "StdError", $hWritePipe) If Not _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, "", DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Then LogMSG("ERR: ExecuteCmd ........: _WinAPI_CreateProcess failed") _WinAPI_CloseHandle($g_hReadPipe) _WinAPI_CloseHandle($hWritePipe) Return False EndIf $h_PID = DllStructGetData($tProcess, "ProcessID") _WinAPI_CloseHandle(DllStructGetData($tProcess, "hProcess")) _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) ; Close the write end of the pipe so that we can read from the read end _WinAPI_CloseHandle($hWritePipe) LogMsg("ExecuteCommand ....: " & $sCmd) Return True EndFunc ;==>ExecuteCmd Func MemoWrite($sMessage = "", $clr = 0) local $CRLF="" If $clr = 1 Then GUICtrlSetData($g_idMemo, "") Else $CRLF=@CRLF EndIf GUICtrlSetData($g_idMemo, $sMessage & $CRLF, 0) EndFunc ;==>MemoWrite Func LogMsg($msg) _GUICtrlStatusBar_SetText($StatusBar1, $msg) EndFunc ;==>LogMsg ; Resize the status bar when GUI size changes Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam _GUICtrlStatusBar_Resize($StatusBar1) Return $GUI_RUNDEFMSG EndFunc ;==>WM_SIZE Func CloseGuiOnDoubleClick($typ) $typ = StringLower($typ) Select Case $typ = "button" If $closecounter = 1 And TimerDiff($TimeHandle) <= $closingdelay Then GUIDelete() Exit EndIf If $closecounter = 0 Then $closecounter = 1 $TimeHandle = TimerInit() WinSetTitle($hGUI, "", "To close, use Slow doubleclick on the X ! Or (2* Alt F4) or (2*Esc)") EndIf Case $typ = "loop" If $closecounter = 1 And TimerDiff($TimeHandle) > $closingdelay Then $closecounter = 0 WinSetTitle($hGUI, "", $formTitle) EndIf EndSelect EndFunc ;==>CloseGuiOnDoubleClick Edit: The script may freeze, if the executed command waits for input. Edited May 15, 2020 by Dan_555 argumentum and Gianni 2 Some of my script sourcecode 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