Jump to content
Sign in to follow this  
PsaltyDS

AutoIt crashes on _NamedPipes_ConnectNamedPipe()

Recommended Posts

Saw another topic on _NamedPipes* functions and wanted to learn a new thing. Did some reading is MSDN and the help file (where there are, distressingly, NO examples of use).

So I tried to code a two-script example for myself. A server side would create the named pipe and connect to it, the client side would then connect to the other end. For a simple demo, the client would write a number to the pipe, the server would read the number, take the cube root, and write it back to the pipe, where the client would read and display it.

Haven't even tried to code the client yet, because the server script crashes hard:

Unhelpful Windows Error message:

Slightly more helpful details (kernel32.dll error):

Here's the unfinished script that causes the error.

When run click "Create Pipe" button, then click "Connect To Pipe".

Warning: Bad things happen (see errors above).

#include <GuiConstants.au3>
#Include <NamedPipes.au3>
#include <array.au3>

Opt("MustDeclareVars", 1)
Opt("GuiOnEventMode", 1)

Global $hNamedPipe = 0, $avPipeData[4]
Global $sNamedPipe = "\\.\pipe\MyNamedPipe"
Global $fSvrConn = False

; Create GUI for server side.
Global $hSvrGUI = GUICreate("Named Pipe SERVER", 600, 360, 50, 50)
GUISetOnEvent($GUI_EVENT_CLOSE, "_ShutDownSvr")
GUICtrlCreateLabel("Purpose of SERVER: Return the cube root of a number via named pipe", 10, 10, 580, 20, $SS_CENTER)
Global $SvrReadEdit = GUICtrlCreateEdit("", 10, 40, 285, 200)
Global $SvrWriteEdit = GUICtrlCreateEdit("", 305, 40, 285, 200)

GUICtrlCreateLabel("Pipe Status:", 10, 265, 150, 20, $SS_RIGHT)
Global $SvrPipeStatus = GUICtrlCreateInput("No pipe created", 170, 265, 150, 20, $SS_LEFT, $ES_READONLY)
GUICtrlCreateButton("Create Pipe", 330, 260, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUICtrlCreateLabel("Connection Status:", 10, 315, 150, 20, $SS_RIGHT)
Global $SvrConnStatus = GUICtrlCreateInput("No connection to pipe", 170, 315, 150, 20, $SS_LEFT, $ES_READONLY)
GUICtrlCreateButton("Connect To Pipe", 330, 310, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUICtrlCreateButton("Pipe Handle State", 465, 285, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUISetState(@SW_SHOW, $hSvrGUI)

While 1
    Sleep(20)
WEnd

Func _ShutDownSvr()
    Exit
EndFunc   ;==>_ShutDownSvr

Func _ButtonHit()
    Local $hGUI_WinHandle = @GUI_WinHandle, $hGUI_CtrlHandle = @GUI_CtrlHandle, $iGUI_CtrlId = @GUI_CtrlId
    Local $sButtonTxt = ControlGetText($hGUI_WinHandle, "", $iGUI_CtrlId)
    ConsoleWrite("Debug: _ButtonHit: Button clicked = " & $sButtonTxt)
    Switch $sButtonTxt
        Case "Create Pipe"
            $hNamedPipe = _NamedPipes_CreateNamedPipe($sNamedPipe)
            If $hNamedPipe <> -1 Then
                ControlSetText($hGUI_WinHandle, "", $SvrPipeStatus, "Pipe successfully created")
                ControlSetText($hGUI_WinHandle, "", $iGUI_CtrlId, "Delete Pipe")
            Else
                ControlSetText($hGUI_WinHandle, "", $SvrPipeStatus, "Error creating pipe")
                ControlSetText($hGUI_WinHandle, "", $iGUI_CtrlId, "Create Pipe")
            EndIf
        Case "Delete Pipe"
            FileClose($hNamedPipe)
            $hNamedPipe = 0
            ControlSetText($hGUI_WinHandle, "", $SvrPipeStatus, "Pipe handle closed")
            ControlSetText($hGUI_WinHandle, "", $iGUI_CtrlId, "Create Pipe")
        Case "Connect To Pipe"
            If _NamedPipes_ConnectNamedPipe($hNamedPipe, 1) Then
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Connected to pipe")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Disconnect From Pipe")
                $fSvrConn = True
            Else
                $fSvrConn = False
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Error connecting to pipe")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Connect To Pipe")
            EndIf
        Case "Disconnect From Pipe"
            If _NamedPipes_DisconnectNamedPipe($hNamedPipe) Then
                $fSvrConn = False
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Pipe disconnected")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Connect To Pipe")
            Else
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Error disconnecting from pipe")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Disconnect From Pipe")
                $fSvrConn = True
            EndIf
        Case "Pipe Handle State"
            _ArrayDisplay(_NamedPipes_GetNamedPipeHandleState($hNamedPipe), "Pipe Handle State")
        Case Else
            MsgBox(16, "Error", "Error!  Function _ButtonHit() unhandled case $sButtonTxt = " & $sButtonTxt)
    EndSwitch
EndFunc   ;==>_ButtonHit

As a first attempt, I'm not surprised my script doesn't work, but I didn't expect full crashes. Are there good demo/example scripts for using named pipes out there that I'm not finding?

:)

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Saw another topic on _NamedPipes* functions and wanted to learn a new thing. Did some reading is MSDN and the help file (where there are, distressingly, NO examples of use).

So I tried to code a two-script example for myself. A server side would create the named pipe and connect to it, the client side would then connect to the other end. For a simple demo, the client would write a number to the pipe, the server would read the number, take the cube root, and write it back to the pipe, where the client would read and display it.

Haven't even tried to code the client yet, because the server script crashes hard:

Unhelpful Windows Error message:

Slightly more helpful details (kernel32.dll error):

Here's the unfinished script that causes the error.

When run click "Create Pipe" button, then click "Connect To Pipe".

Warning: Bad things happen (see errors above).

#include <GuiConstants.au3>
#Include <NamedPipes.au3>
#include <array.au3>

Opt("MustDeclareVars", 1)
Opt("GuiOnEventMode", 1)

Global $hNamedPipe = 0, $avPipeData[4]
Global $sNamedPipe = "\\.\pipe\MyNamedPipe"
Global $fSvrConn = False

; Create GUI for server side.
Global $hSvrGUI = GUICreate("Named Pipe SERVER", 600, 360, 50, 50)
GUISetOnEvent($GUI_EVENT_CLOSE, "_ShutDownSvr")
GUICtrlCreateLabel("Purpose of SERVER: Return the cube root of a number via named pipe", 10, 10, 580, 20, $SS_CENTER)
Global $SvrReadEdit = GUICtrlCreateEdit("", 10, 40, 285, 200)
Global $SvrWriteEdit = GUICtrlCreateEdit("", 305, 40, 285, 200)

GUICtrlCreateLabel("Pipe Status:", 10, 265, 150, 20, $SS_RIGHT)
Global $SvrPipeStatus = GUICtrlCreateInput("No pipe created", 170, 265, 150, 20, $SS_LEFT, $ES_READONLY)
GUICtrlCreateButton("Create Pipe", 330, 260, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUICtrlCreateLabel("Connection Status:", 10, 315, 150, 20, $SS_RIGHT)
Global $SvrConnStatus = GUICtrlCreateInput("No connection to pipe", 170, 315, 150, 20, $SS_LEFT, $ES_READONLY)
GUICtrlCreateButton("Connect To Pipe", 330, 310, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUICtrlCreateButton("Pipe Handle State", 465, 285, 100, 30)
GUICtrlSetOnEvent(-1, "_ButtonHit")

GUISetState(@SW_SHOW, $hSvrGUI)

While 1
    Sleep(20)
WEnd

Func _ShutDownSvr()
    Exit
EndFunc   ;==>_ShutDownSvr

Func _ButtonHit()
    Local $hGUI_WinHandle = @GUI_WinHandle, $hGUI_CtrlHandle = @GUI_CtrlHandle, $iGUI_CtrlId = @GUI_CtrlId
    Local $sButtonTxt = ControlGetText($hGUI_WinHandle, "", $iGUI_CtrlId)
    ConsoleWrite("Debug: _ButtonHit: Button clicked = " & $sButtonTxt)
    Switch $sButtonTxt
        Case "Create Pipe"
            $hNamedPipe = _NamedPipes_CreateNamedPipe($sNamedPipe)
            If $hNamedPipe <> -1 Then
                ControlSetText($hGUI_WinHandle, "", $SvrPipeStatus, "Pipe successfully created")
                ControlSetText($hGUI_WinHandle, "", $iGUI_CtrlId, "Delete Pipe")
            Else
                ControlSetText($hGUI_WinHandle, "", $SvrPipeStatus, "Error creating pipe")
                ControlSetText($hGUI_WinHandle, "", $iGUI_CtrlId, "Create Pipe")
            EndIf
        Case "Delete Pipe"
            FileClose($hNamedPipe)
            $hNamedPipe = 0
            ControlSetText($hGUI_WinHandle, "", $SvrPipeStatus, "Pipe handle closed")
            ControlSetText($hGUI_WinHandle, "", $iGUI_CtrlId, "Create Pipe")
        Case "Connect To Pipe"
            If _NamedPipes_ConnectNamedPipe($hNamedPipe, 1) Then
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Connected to pipe")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Disconnect From Pipe")
                $fSvrConn = True
            Else
                $fSvrConn = False
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Error connecting to pipe")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Connect To Pipe")
            EndIf
        Case "Disconnect From Pipe"
            If _NamedPipes_DisconnectNamedPipe($hNamedPipe) Then
                $fSvrConn = False
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Pipe disconnected")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Connect To Pipe")
            Else
                ControlSetText($hSvrGUI, "", $SvrConnStatus, "Error disconnecting from pipe")
                ControlSetText($hSvrGUI, "", $iGUI_CtrlId, "Disconnect From Pipe")
                $fSvrConn = True
            EndIf
        Case "Pipe Handle State"
            _ArrayDisplay(_NamedPipes_GetNamedPipeHandleState($hNamedPipe), "Pipe Handle State")
        Case Else
            MsgBox(16, "Error", "Error!  Function _ButtonHit() unhandled case $sButtonTxt = " & $sButtonTxt)
    EndSwitch
EndFunc   ;==>_ButtonHit

As a first attempt, I'm not surprised my script doesn't work, but I didn't expect full crashes. Are there good demo/example scripts for using named pipes out there that I'm not finding?

:)

I know nothing about pipes I'm afraid, but did you know there is a client/server example in the @ProgramFiles\AutoIt3\Auto3Lib\Pipes? Also some explanation in the UDF help file.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

I know nothing about pipes I'm afraid, but did you know there is a client/server example in the @ProgramFiles\AutoIt3\Auto3Lib\Pipes? Also some explanation in the UDF help file.

Didn't realize that demo was there. I did read the function headers and scan the code in the UDF. Pretty dense stuff (or pretty dense reader). But I'm trying to absorb it.

Client and Server Converted, not tested, too much going on my system at this time to test.

Those demos work fine. Thanks Gary. All I have to do now is understand it all!

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

I'm having a hard time getting named pipes, which are perfect for a project that I'm working on, to work properly. Unfortunately, the attachments with examples are no longer attached, and the demo referenced in the auto3lib directory no longer comes with an installation. Also I downloaded some archived versions of AutoIt3 and can't find it in those, either. I tried to follow along with an example in C, but it didn't work for me.

So, anyone have a quick named pipe client/server example they can share? I would appreciate it very much!

Thanks,

Kevin

Share this post


Link to post
Share on other sites

The demos are part of PaulIA's original AU3 Library functions, not part of the AutoIt distribution. The original topic is here: Auto3Lib, A library of functions for AutoIt

The files are not attached and the topic is closed because Paul isn't around anymore and doesn't support it. The standardization of Global CONST variables across the UDFs has broken a lot of that code, so you won't get support either from Paul or the AutoIt devs for the old versions.

Here are the original examples if you want to play with them:

Here is the readme file Pipes.txt:

Special thanks to Yoan Roblet (Arcker) for his help in developing the Pipes module

for Auto3Lib. Yoan provided the ground work for the development of the pipe UDFs

and was instrumental in providing help and support during the debug phase.

Console.au3

-----------

This demo shows how to execute a console command and read the output of the command

using a one way pipe.

Client.au3

-----------

This is the client part of the client/server pipe demo. It allows you to execute

console commands on a local or remote computer and view the output. If you run the

server part on a remote machine, you must have established network credentials on

the remote machine.

Server.au3

-----------

This is the server part of the client/server pipe demo. You must run this part of

the demo on a local or remote machine BEFORE using the client part.

Here is Console.au3:

CODE
#include <A3LPipes.au3>

#include <A3LWinAPI.au3>

Opt("MustDeclareVars", 1)

; ====================================================================================================

===========================

; Description ...: Shows how to use pipe functions to read the output from a console operation

; Author ........: Paul Campbell (PaulIA)

; Notes .........: This script MUST be run in SciTE in order to see the results

; ====================================================================================================

===========================

; ====================================================================================================

===========================

; Main

; ====================================================================================================

===========================

ExecuteCmd("cmd.exe /c dir c:\windows")

;ExecuteCmd("ping www.autoit.com")

; ====================================================================================================

===========================

; Execute a command and display the results

; ====================================================================================================

===========================

Func ExecuteCmd($sCmd)

Local $iBytes, $sData, $hReadPipe, $hWritePipe, $tBuffer, $tProcess, $tSecurity, $tStartup

; 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

_Pipe_CreatePipe($hReadPipe, $hWritePipe, $tSecurity)

; 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)

_API_CreateProcess("", $sCmd, 0, 0, True, 0, 0, "", DllStructGetPtr($tStartup), DllStructGetPtr($tProcess))

_API_CloseHandle(DllStructGetData($tProcess, "hProcess"))

_API_CloseHandle(DllStructGetData($tProcess, "hThread"))

; Close the write end of the pipe before reading from the read end of the pipe

_API_CloseHandle($hWritePipe)

; Read data from the child process

$tBuffer = DllStructCreate("char Text[4096]")

While 1

_API_ReadFile($hReadPipe, DllStructGetPtr($tBuffer), 4096, $iBytes)

If $iBytes = 0 Then ExitLoop

$sData = StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes)

$sData = StringReplace($sData, @CR & @CR, @CR)

ConsoleWrite($sData)

WEnd

EndFunc ;==>ExecuteCmd

Here is Client.au3:

CODE
#include <A3LPipes.au3>

Opt("MustDeclareVars", 1)

; ====================================================================================================

===========================

; Description ...: This is the client side of the pipe demo

; Author ........: Paul Campbell (PaulIA)

; Notes .........:

; ====================================================================================================

===========================

; ====================================================================================================

===========================

; Global constants

; ====================================================================================================

===========================

Global Const $BUFSIZE = 4096

Global Const $DEFCMD = "cmd.exe /c dir c:\windows /s"

Global Const $PIPE_NAME = "\\$\\pipe\\Auto3Lib"

; ====================================================================================================

===========================

; Global variables

; ====================================================================================================

===========================

Global $iEdit, $iMemo, $iSend, $iServer, $hPipe

; ====================================================================================================

===========================

; Main

; ====================================================================================================

===========================

CreateGUI()

MsgLoop()

; ====================================================================================================

===========================

; Creates a GUI for the client

; ====================================================================================================

===========================

Func CreateGUI()

Local $hGUI, $iLabel1, $iLabel2

$hGUI = GUICreate("Pipe Client", 500, 400, -1, -1, $WS_SIZEBOX)

$iLabel1 = GUICtrlCreateLabel("Server:", 2, 14, 52, 20, $SS_RIGHT)

$iServer = GUICtrlCreateEdit("<local>", 56, 10, 200, 20, $SS_LEFT)

$iLabel2 = GUICtrlCreateLabel("Command:", 2, 36, 52, 20, $SS_RIGHT)

$iEdit = GUICtrlCreateEdit($DEFCMD, 56, 32, 370, 20, $SS_LEFT)

$iSend = GUICtrlCreateButton("Send", 430, 32, 60, 20)

$iMemo = GUICtrlCreateEdit("", 0, 62, _API_GetClientWidth($hGUI), 332)

GUICtrlSetFont($iMemo, 9, 400, 0, "Courier New")

GUISetState()

EndFunc ;==>CreateGUI

; ====================================================================================================

===========================

; Logs an error message to the display

; ====================================================================================================

===========================

Func LogError($sMessage)

$sMessage &= " (" & _API_GetLastErrorMessage() & ")"

GUICtrlSetData($iMemo, GUICtrlRead($iMemo) & $sMessage & @CRLF)

EndFunc ;==>LogError

; ====================================================================================================

===========================

; Logs a message to the display

; ====================================================================================================

===========================

Func LogMsg($sMessage)

GUICtrlSetData($iMemo, GUICtrlRead($iMemo) & $sMessage & @CRLF)

EndFunc ;==>LogMsg

; ====================================================================================================

===========================

; MsgLoop

; ====================================================================================================

===========================

Func MsgLoop()

While True

Switch GUIGetMsg()

Case $iSend

SendCmd()

Case $GUI_EVENT_CLOSE

Exit

EndSwitch

WEnd

EndFunc ;==>MsgLoop

; ====================================================================================================

===========================

; This function opens a pipe to the server

; ====================================================================================================

===========================

Func OpenPipe()

Local $sName, $sPipe

; Get pipe handle

$sName = GUICtrlRead($iServer)

If $sName = "<local>" Then $sName = "."

$sPipe = StringReplace($PIPE_NAME, "$", $sName)

$hPipe = _API_CreateFile($sPipe, 2, 6)

If $hPipe <> -1 Then Return True

LogError("OpenPipe failed")

Return False

EndFunc ;==>OpenPipe

; ====================================================================================================

===========================

; This function reads a message from the pipe

; ====================================================================================================

===========================

Func ReadMsg()

Local $bSuccess, $iRead, $pBuffer, $tBuffer

$tBuffer = DllStructCreate("char Text[4096]")

$pBuffer = DllStructGetPtr($tBuffer)

GUICtrlSetData($iMemo, "")

While 1

$bSuccess = _API_ReadFile($hPipe, $pBuffer, $BUFSIZE, $iRead, 0)

If $iRead = 0 Then ExitLoop

If Not $bSuccess Or (@error = $ERROR_MORE_DATA) Then ExitLoop

GUICtrlSetData($iMemo, StringLeft(DllStructGetData($tBuffer, "Text"), $iRead), 1)

WEnd

EndFunc ;==>ReadMsg

; ====================================================================================================

===========================

; This function sends a command to the server

; ====================================================================================================

===========================

Func SendCmd()

If OpenPipe() Then

SetReadMode()

WriteMsg(GUICtrlRead($iEdit))

ReadMsg()

_API_CloseHandle($hPipe)

EndIf

EndFunc ;==>SendCmd

; ====================================================================================================

===========================

; This function sets the pipe read mode

; ====================================================================================================

===========================

Func SetReadMode()

If Not _Pipe_SetNamedPipeHandleState($hPipe, 1, 0, 0, 0) Then

LogError("SetReadMode: _Pipe_SetNamedPipeHandleState failed")

EndIf

EndFunc ;==>SetReadMode

; ====================================================================================================

===========================

; This function writes a message to the pipe

; ====================================================================================================

===========================

Func WriteMsg($sMessage)

Local $iWritten, $iBuffer, $pBuffer, $tBuffer

$iBuffer = StringLen($sMessage) + 1

$tBuffer = DllStructCreate("char Text[" & $iBuffer & "]")

$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tBuffer, "Text", $sMessage)

If Not _API_WriteFile($hPipe, $pBuffer, $iBuffer, $iWritten, 0) Then

LogError("WriteMsg: _API_WriteFile failed")

EndIf

EndFunc ;==>WriteMsg

Here is Server.au3:

CODE
#include <A3LPipes.au3>

Opt("MustDeclareVars", 1)

; ====================================================================================================

===========================

; Description ...: This is the server side of the pipe demo

; Author ........: Paul Campbell (PaulIA)

; Notes .........:

; ====================================================================================================

===========================

; ====================================================================================================

===========================

; Global constants

; ====================================================================================================

===========================

Global Const $DEBUGGING = False

Global Const $BUFSIZE = 4096

Global Const $PIPE_NAME = "\\.\\pipe\\Auto3Lib"

Global Const $TIMEOUT = 5000

; ====================================================================================================

===========================

; Global variables

; ====================================================================================================

===========================

Global $hEvent, $iMemo, $pOverlap, $tOverlap, $hPipe, $hReadPipe, $iState, $iToWrite

; ====================================================================================================

===========================

; Main

; ====================================================================================================

===========================

CreateGUI()

InitPipe()

MsgLoop()

; ====================================================================================================

===========================

; Creates a GUI for the server

; ====================================================================================================

===========================

Func CreateGUI()

Local $hGUI

$hGUI = GUICreate("Pipe Server", 500, 400, -1, -1, $WS_SIZEBOX)

$iMemo = GUICtrlCreateEdit("", 0, 0, _API_GetClientWidth($hGUI), _API_GetClientHeight($hGUI))

GUICtrlSetFont($iMemo, 9, 400, 0, "Courier New")

GUISetState()

EndFunc ;==>CreateGUI

; ====================================================================================================

===========================

; This function creates an instance of a named pipe

; ====================================================================================================

===========================

Func InitPipe()

; Create an event object for the instance

$tOverlap = DllStructCreate($tagOVERLAPPED)

$pOverlap = DllStructGetPtr($tOverlap)

$hEvent = _API_CreateEvent()

If $hEvent = 0 Then

LogError("InitPipe ..........: API_CreateEvent failed")

Return

EndIf

DllStructSetData($tOverlap, "hEvent", $hEvent)

; Create a named pipe

$hPipe = _Pipe_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 $hPipe = -1 Then

LogError("InitPipe ..........: _Pipe_CreateNamedPipe failed")

Else

; Connect pipe instance to client

ConnectClient()

EndIf

EndFunc ;==>InitPipe

; ====================================================================================================

===========================

; This function loops waiting for a connection event or the GUI to close

; ====================================================================================================

===========================

Func MsgLoop()

Local $iEvent

Do

$iEvent = _API_WaitForSingleObject($hEvent, 0)

If $iEvent < 0 Then

LogError("MsgLoop ...........: _API_WaitForSingleObject failed")

Exit

EndIf

If $iEvent = $WAIT_TIMEOUT Then ContinueLoop

Debug("MsgLoop ...........: Instance signaled")

Switch $iState

Case 0

CheckConnect()

Case 1

ReadRequest()

Case 2

CheckPending()

Case 3

RelayOutput()

EndSwitch

Until GUIGetMsg() = $GUI_EVENT_CLOSE

EndFunc ;==>MsgLoop

; ====================================================================================================

===========================

; Checks to see if the pending client connection has finished

; ====================================================================================================

===========================

Func CheckConnect()

Local $iBytes

; Was the operation successful?

If Not _API_GetOverlappedResult($hPipe, $pOverlap, $iBytes, False) Then

LogError("CheckConnect ......: Connection failed")

ReconnectClient()

Else

LogMsg("CheckConnect ......: Connected")

$iState = 1

EndIf

EndFunc ;==>CheckConnect

; ====================================================================================================

===========================

; This function reads a request message from the client

; ====================================================================================================

===========================

Func ReadRequest()

Local $pBuffer, $tBuffer, $iRead, $bSuccess, $iToWrite

$tBuffer = DllStructCreate("char Text[" & $BUFSIZE & "]")

$pBuffer = DllStructGetPtr($tBuffer)

$bSuccess = _API_ReadFile($hPipe, $pBuffer, $BUFSIZE, $iRead, $pOverlap)

If $bSuccess And ($iRead <> 0) Then

; The read operation completed successfully

Debug("ReadRequest .......: Read success")

Else

; Wait for read Buffer to complete

If Not _API_GetOverlappedResult($hPipe, $pOverlap, $iRead, True) Then

LogError("ReadRequest .......: _API_GetOverlappedResult failed")

ReconnectClient()

Return

Else

; Read the command from the pipe

$bSuccess = _API_ReadFile($hPipe, $pBuffer, $BUFSIZE, $iRead, $pOverlap)

If Not $bSuccess Or ($iRead = 0) Then

LogError("ReadRequest .......: _API_ReadFile failed")

ReconnectClient()

Return

EndIf

EndIf

EndIf

; Execute the console command

If Not ExecuteCmd(DllStructGetData($tBuffer, "Text")) Then

ReconnectClient()

Return

EndIf

; Relay console output back to the client

$iState = 3

EndFunc ;==>ReadRequest

; ====================================================================================================

===========================

; This function relays the console output back to the client

; ====================================================================================================

===========================

Func CheckPending()

Local $bSuccess, $iWritten

$bSuccess = _API_GetOverlappedResult($hPipe, $pOverlap, $iWritten, False)

If Not $bSuccess Or ($iWritten <> $iToWrite) Then

Debug("CheckPending ......: Write reconnecting")

ReconnectClient()

Else

Debug("CheckPending ......: Write complete")

$iState = 3

EndIf

EndFunc ;==>CheckPending

; ====================================================================================================

===========================

; This function relays the console output back to the client

; ====================================================================================================

===========================

Func RelayOutput()

Local $pBuffer, $tBuffer, $sLine, $iRead, $bSuccess, $iWritten

$tBuffer = DllStructCreate("char Text[" & $BUFSIZE & "]")

$pBuffer = DllStructGetPtr($tBuffer)

; Read data from console pipe

_API_ReadFile($hReadPipe, $pBuffer, $BUFSIZE, $iRead)

If $iRead = 0 Then

LogMsg("RelayOutput .......: Write done")

_API_CloseHandle($hReadPipe)

_API_FlushFileBuffers($hPipe)

ReconnectClient()

Return

EndIf

; Get the data and strip out the extra carriage returns

$sLine = StringLeft(DllStructGetData($tBuffer, "Text"), $iRead)

$sLine = StringReplace($sLine, @CR & @CR, @CR)

$iToWrite = StringLen($sLine)

DllStructSetData($tBuffer, "Text", $sLine)

; Relay the data back to the client

$bSuccess = _API_WriteFile($hPipe, $pBuffer, $iToWrite, $iWritten, $pOverlap)

If $bSuccess And ($iWritten = $iToWrite) Then

Debug("RelayOutput .......: Write success")

Else

If Not $bSuccess And (@error = $ERROR_IO_PENDING) Then

Debug("RelayOutput .......: Write pending")

$iState = 2

Else

; An error occurred, disconnect from the client

LogError("RelayOutput .......: Write failed")

ReconnectClient()

EndIf

EndIf

EndFunc ;==>RelayOutput

; ====================================================================================================

===========================

; This function is called to start an overlapped connection operation

; ====================================================================================================

===========================

Func ConnectClient()

$iState = 0

; Start an overlapped connection

If _Pipe_ConnectNamedPipe($hPipe, $pOverlap) Then

LogError("ConnectClient .....: ConnectNamedPipe 1 failed")

Else

Switch @error

; The overlapped connection is in progress

Case $ERROR_IO_PENDING

Debug("ConnectClient .....: Pending")

; Client is already connected, so signal an event

Case $ERROR_PIPE_CONNECTED

LogMsg("ConnectClient .....: Connected")

$iState = 1

If Not _API_SetEvent(DllStructGetData($tOverlap, "hEvent")) Then

LogError("ConnectClient .....: SetEvent failed")

EndIf

; Error occurred during the connection event

Case Else

LogError("ConnectClient .....: ConnectNamedPipe 2 failed")

EndSwitch

EndIf

EndFunc ;==>ConnectClient

; ====================================================================================================

===========================

; Dumps debug information to the screen

; ====================================================================================================

===========================

Func Debug($sMessage)

If $DEBUGGING Then LogMsg($sMessage)

EndFunc ;==>Debug

; ====================================================================================================

===========================

; 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 _Pipe_CreatePipe($hReadPipe, $hWritePipe, $tSecurity) Then

LogError("ExecuteCmd ........: _Pipe_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 _API_CreateProcess("", $sCmd, 0, 0, True, 0, 0, "", DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Then

LogError("ExecuteCmd ........: _API_CreateProcess failed")

_API_CloseHandle($hReadPipe)

_API_CloseHandle($hWritePipe)

Return False

EndIf

_API_CloseHandle(DllStructGetData($tProcess, "hProcess"))

_API_CloseHandle(DllStructGetData($tProcess, "hThread"))

; Close the write end of the pipe so that we can read from the read end

_API_CloseHandle($hWritePipe)

LogMsg("ExecuteCommand ....: " & $sCmd)

Return True

EndFunc ;==>ExecuteCmd

; ====================================================================================================

===========================

; Logs an error message to the display

; ====================================================================================================

===========================

Func LogError($sMessage)

$sMessage &= " (" & _API_GetLastErrorMessage() & ")"

_Lib_ConsoleWrite($sMessage)

EndFunc ;==>LogError

; ====================================================================================================

===========================

; Logs a message to the display

; ====================================================================================================

===========================

Func LogMsg($sMessage)

GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)

EndFunc ;==>LogMsg

; ====================================================================================================

===========================

; This function is called when an error occurs or when the client closes its handle to the pipe

; ====================================================================================================

===========================

Func ReconnectClient()

; Disconnect the pipe instance

If Not _Pipe_DisconnectNamedPipe($hPipe) Then

LogError("ReconnectClient ...: DisonnectNamedPipe failed")

Return

EndIf

; Connect to a new client

ConnectClient()

EndFunc ;==>ReconnectClient

Good luck with it.

:D


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

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
Sign in to follow this  

×
×
  • Create New...