Code-Beispiel
bipipe.bi
Die hier vorgestellte Bibliothek stellt - per #Include eingebunden - 5 Funktionen zur Verfügung:
- bipOpen(ProgrammName, [showmode] ) - Öffnet das (Konsolen-)programm ProgrammName und richtet zwei unidirektionale Pipes zur Kommunikation ein. Der optionale Parameter showmode legt die Erscheinungsweise des aufgerufenen Programms fest. Mögliche Parameter siehe hier. Default ist SW_NORMAL. Der Rückgabewert ist ein Pointer auf das entsprechende HANDLE - Array (HandlePointer).
- bipClose(HandlePointer) - Beendet das Programm, schließt die Pipes, löscht die Handles, gibt den Speicher frei und setzt den HandlePointer auf 0.
- bipWrite(HandlePointer, text, ["b"]) - Sendet einen String zur Standardeingabe des geöffneten Programms. Wird der optionale Parameter "b" (für binary) gesetzt, wird der String unverändert gesendet, ansonsten wird noch ein Chr(13,10) angehängt.
- bipRead(HandlePointer, [timeout]) - Liest die Standardausgabe des Programms. Default für timeout ist 100ms.
- bipReadLine(HandlePointer, [separator], [timeout]) - Liest eine Zeile vom gestarteten Programm, analog zum "Line Input" - Befehl. Der optionale Parameter separator ist entweder ein "a" (für any), gefolgt von einer Liste von Zeichen, von denen jedes die Zeile beendet, oder ein "e" (für exact), gefolgt von einem oder mehreren Zeichen, das den Separator darstellt. Default ist "a" & Chr(13,10). Default für timeout ist 100ms.
English
(translated by chris319)
The library presented here provides 5 functions - integrated via #Include:
1. bipOpen (ProgrammName, [showmode]) - Opens the (console) program ProgrammName and sets up two unidirectional pipes for communication. The optional parameter showmode defines the appearance of the called program. For possible parameters see https://docs.microsoft.com/en-us/window ... dfrom=MSDN. The default is SW_NORMAL. The return value is a pointer to the corresponding HANDLE array (HandlePointer).
2. bipClose (HandlePointer) - Ends the program, closes the pipes, clears the handles, releases the memory and sets the HandlePointer to 0.
3. bipWrite (HandlePointer, text, ["b"]) - Sends a string for standard input of the opened program. If the optional parameter "b" (for binary) is set, the string is sent unchanged, otherwise a Chr (13,10) is added.
4. bipRead (HandlePointer, [timeout]) - Reads the standard output of the program. The default for timeout is 100ms.
5. bipReadLine (HandlePointer, [separator], [timeout]) - Reads a line from the started program, analogous to the "Line Input" command. The optional separator parameter is either an "a" (for any) followed by a list of characters, each of which ends the line, or an "e" (for exact), followed by one or more characters to represent the separator , The default is "a" & Chr (13,10). The default for timeout is 100ms.
#Include Once "windows.bi"
Type bipdata
hProcessHandle As HANDLE
hWritePipe As HANDLE
hReadPipe As HANDLE
End Type
Function bipOpen(PrgName As String, showmode As Short = SW_NORMAL) As bipdata Ptr
Dim As STARTUPINFO si
Dim As PROCESS_INFORMATION pi
Dim As SECURITY_ATTRIBUTES sa
Dim As HANDLE hReadPipe, hWritePipe, hReadChildPipe, hWriteChildPipe
Dim pPipeHandles As bipdata Ptr
'set security attributes
sa.nLength = SizeOf(SECURITY_ATTRIBUTES)
sa.lpSecurityDescriptor = NULL 'use default descriptor
sa.bInheritHandle = TRUE
'create one pipe for each direction
CreatePipe(@hReadChildPipe,@hWritePipe,@sa,0) 'parent to child
CreatePipe(@hReadPipe,@hWriteChildPipe,@sa,0) 'child to parent
GetStartupInfo(@si)
si.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
si.wShowWindow = showmode 'appearance of child process window
si.hStdOutput = hWriteChildPipe
si.hStdError = hWriteChildPipe
si.hStdInput = hReadChildPipe
CreateProcess(0,PrgName,0,0,TRUE,CREATE_NEW_CONSOLE,0,0,@si,@pi)
CloseHandle(hWriteChildPipe)
CloseHandle(hReadChildPipe)
pPipeHandles = Allocate (SizeOf(bipdata)) 'area for storing the handles
pPipeHandles->hProcessHandle = pi.hProcess 'handle to child process
pPipeHandles->hWritePipe = hWritePipe
pPipeHandles->hReadPipe = hReadPipe
Return pPipeHandles 'pointer to handle array
End Function
Sub bipClose(ByRef pPipeHandles As bipdata Ptr)
If pPipeHandles = 0 Then Return
TerminateProcess(pPipeHandles->hProcessHandle, 0)
CloseHandle(pPipeHandles->hWritePipe)
CloseHandle(pPipeHandles->hReadPipe)
DeAllocate(pPipeHandles)
pPipeHandles = 0
End Sub
Function bipWrite(pPipeHandles As bipdata Ptr, text As String, mode As String = "") As Integer
Dim As Integer iNumberOfBytesWritten
'Dim As String txt = text
'? Len(text);" ";
If pPipeHandles = 0 Then Return 0
If LCase(mode) <> "b" Then 'not binary mode
text += Chr(13,10)
EndIf
WriteFile(pPipeHandles->hWritePipe,StrPtr(text),Len(text),@iNumberOfBytesWritten,0)
Return iNumberOfBytesWritten
End Function
Function bipRead(pPipeHandles As bipdata Ptr, timeout As UInteger = 100) As String
'returns the whole pipe content until the pipe is empty or timeout occurs.
' timeout default is 100ms to prevent a deadlock
Dim As Integer iNumberOfBytesRead, iTotalBytesAvail, iBytesLeftThisMessage
Dim As String buffer, retText
Dim As Double tout = Timer + Cast(Double,timeout) / 1000
If pPipeHandles = 0 Then Return "" 'no valid pointer
Do
PeekNamedPipe(pPipeHandles->hReadPipe,0,0,0,@iTotalBytesAvail,0)
If iTotalBytesAvail Then
buffer = String(iTotalBytesAvail,Chr(0))
ReadFile(pPipeHandles->hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead,0)
retText &= buffer
ElseIf Len(retText) Then
Exit Do
EndIf
Loop Until Timer > tout
Return retText
End Function
Function bipReadLine(pPipeHandles As bipdata Ptr, separator As String = "a" & Chr(13,10), timeout As UInteger = 100) As String
'returns the pipe content till the first separator if any, or otherwise the whole pipe
' content on timeout. timeout default is 100ms to prevent a deadlock
Dim As Integer iNumberOfBytesRead, iTotalBytesAvail, iBytesLeftThisMessage, endPtr
Dim As String buffer, retText, mode
Dim As Double tout = Timer + Cast(Double,timeout) / 1000
If pPipeHandles = 0 Then Return "" 'no valid pointer
mode = LCase(Left(separator,1))
separator = Mid(separator,2)
Do
PeekNamedPipe(pPipeHandles->hReadPipe,0,0,0,@iTotalBytesAvail,0)
If iTotalBytesAvail Then
buffer = String(iTotalBytesAvail,Chr(0))
PeekNamedPipe(pPipeHandles->hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead, _
@iTotalBytesAvail,@iBytesLeftThisMessage) 'copy pipe content to buffer
Select Case mode
Case "a" 'any
endPtr = InStr(buffer, Any separator) 'look for line end sign
Case "e" 'exact
endPtr = InStr(buffer, separator) 'look for line end sign
End Select
If endPtr Then 'return pipe content till line end
Select Case mode
Case "a"
Do While (InStr(separator,Chr(buffer[endPtr - 1]))) And (endPtr < Len(buffer))
endPtr += 1
Loop
endPtr -= 1
Case "e"
endPtr += Len(separator)
End Select
retText = Left(buffer,endPtr)
ReadFile(pPipeHandles->hReadPipe,StrPtr(buffer),endPtr,@iNumberOfBytesRead,0) 'remove read bytes from pipe
Select Case mode
Case "a"
Return RTrim(retText,Any separator) 'remove line end sign from returned string
Case "e"
Return Left(retText,Len(retText) - Len(separator))
End Select
EndIf
EndIf
Loop Until Timer > tout
If iTotalBytesAvail Then 'return all pipe content
buffer = String(iTotalBytesAvail,Chr(0))
ReadFile(pPipeHandles->hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead,0)
Return buffer
EndIf
Return ""
End Function
Zusätzliche Informationen und Funktionen |
- Das Code-Beispiel wurde am 03.06.2015 von grindstone angelegt.
- Die aktuellste Version wurde am 05.03.2020 von grindstone gespeichert.
|
|