Konsole auslesen

Anfängerfragen zum Programmieren mit PureBasic.
BitchBird
Beiträge: 17
Registriert: 09.11.2004 10:29

Konsole auslesen

Beitrag von BitchBird »

hallo!

ich starte per RunProgram() ein programm, welches in der konsole läuft. nun möchte ich aber in meinem fenster diese konsole darstellen, so dass sie nicht extra aufpoppt sondern in einem gadget o.ä, dargestellt wird.

wie kann man sowas realisieren?
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

Code: Alles auswählen

#D_ReadBufferSize = 1024

Structure D_ProgramInfo
  StartUpInfo.STARTUPINFO
  ProcessInfo.PROCESS_INFORMATION
  SECURITYATTRIBUTES.SECURITY_ATTRIBUTES
  hOutputPipeRead.l
  hOutputPipeWrite.l
  hInputPipeRead.l
  hInputPipeWrite.l
  hReadThread.l
  ReadThreadStat.l
  ReadBuffer.l
  ReadDataLen.l
EndStructure

Procedure D_ReadConsoleOutputThread(*ProgramInfo.D_ProgramInfo)
  *ProgramInfo\ReadBuffer = AllocateMemory(#D_ReadBufferSize)
  *ProgramInfo\ReadThreadStat = 1
  Repeat
    If *ProgramInfo\ReadThreadStat = 1
      If ReadFile_(*ProgramInfo\hOutputPipeRead,*ProgramInfo\ReadBuffer,#D_ReadBufferSize,@*ProgramInfo\ReadDataLen,0)
        *ProgramInfo\ReadThreadStat = 2
      EndIf
    EndIf
    Delay(1)
  Until *ProgramInfo\ReadThreadStat = 0
  FreeMemory(*ProgramInfo\ReadBuffer)
  *ProgramInfo\hReadThread = #Null
EndProcedure

Procedure D_RunProgram(EXEFileName.s,Parameter.s,*ProgramInfo.D_ProgramInfo)
  Protected result
  result = #False
  *ProgramInfo\SECURITYATTRIBUTES\nLength = SizeOf(SECURITY_ATTRIBUTES)
  *ProgramInfo\SECURITYATTRIBUTES\bInheritHandle = 1
  *ProgramInfo\SECURITYATTRIBUTES\lpSecurityDescriptor = 0
 
  If CreatePipe_(@*ProgramInfo\hOutputPipeRead, @*ProgramInfo\hOutputPipeWrite, @*ProgramInfo\SECURITYATTRIBUTES, 0) And CreatePipe_(@*ProgramInfo\hInputPipeRead, @*ProgramInfo\hInputPipeWrite, @*ProgramInfo\SECURITYATTRIBUTES, 0)
    *ProgramInfo\StartUpInfo\cb = SizeOf(STARTUPINFO)
    *ProgramInfo\StartUpInfo\dwFlags = #STARTF_USESTDHANDLES | #STARTF_USESHOWWINDOW
    *ProgramInfo\StartUpInfo\hStdOutput = *ProgramInfo\hOutputPipeWrite
    *ProgramInfo\StartUpInfo\hStdError = *ProgramInfo\hOutputPipeWrite
    *ProgramInfo\StartUpInfo\hStdInput = *ProgramInfo\hInputPipeRead
    If CreateProcess_(#Null,Chr(34)+EXEFileName+Chr(34)+" "+Parameter,@*ProgramInfo\SECURITYATTRIBUTES,@*ProgramInfo\SECURITYATTRIBUTES,1,#NORMAL_PRIORITY_CLASS,#Null,#Null,@*ProgramInfo\StartUpInfo,@*ProgramInfo\ProcessInfo)
      *ProgramInfo\hReadThread = CreateThread(@D_ReadConsoleOutputThread(),*ProgramInfo)
      If *ProgramInfo\hReadThread
        Delay(10)
        result = #True
      EndIf
    EndIf
    CloseHandle_(*ProgramInfo\hOutputPipeWrite)
    CloseHandle_(*ProgramInfo\hInputPipeRead)
  EndIf
  ProcedureReturn result
EndProcedure

Procedure D_CloseProgram(*ProgramInfo.D_ProgramInfo)
  *ProgramInfo\ReadThreadStat = 0
  CloseHandle_(*ProgramInfo\ProcessInfo\hThread)
  CloseHandle_(*ProgramInfo\hOutputPipeRead)
  CloseHandle_(*ProgramInfo\hInputPipeWrite)
  TerminateProcess_(*ProgramInfo\ProcessInfo\hProcess,0)
  CloseHandle_(*ProgramInfo\ProcessInfo\hProcess)
  If *ProgramInfo\hReadThread
    KillThread(*ProgramInfo\hReadThread)
  EndIf
EndProcedure

Procedure D_GetOutput(*ProgramInfo.D_ProgramInfo,Buffer)
  Delay(5)
  If *ProgramInfo\ReadThreadStat = 2
    Debug *ProgramInfo\ReadBuffer
    Debug OemToCharBuff_(*ProgramInfo\ReadBuffer,Buffer,*ProgramInfo\ReadDataLen)
    *ProgramInfo\ReadThreadStat = 1
    ProcedureReturn *ProgramInfo\ReadDataLen
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure D_SendInputString(*ProgramInfo.D_ProgramInfo,string.s)
  Protected tmp.l
  CharToOemBuff_(string,string,Len(string))
  If WriteFile_(*ProgramInfo\hInputPipeWrite,string,Len(string),@tmp,0)
    ProcedureReturn tmp
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure D_SendInput(*ProgramInfo.D_ProgramInfo,Buffer.l,Bufferlen.l)
  Protected tmp.l
  If WriteFile_(*ProgramInfo\hInputPipeWrite,Buffer,Bufferlen,@tmp,0)
    ProcedureReturn tmp
  EndIf
  ProcedureReturn #False
EndProcedure


#Gadget_String = 0

CreateGadgetList(OpenWindow(0,0,0,400,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Console-Zeugs"))
StringGadget(#Gadget_String,0,0,400,200,"",#PB_String_MultiLine|#PB_String_ReadOnly)


Mem = AllocateMemory(#D_ReadBufferSize)

If D_RunProgram("ping","localhost",@ProgramInfo.D_ProgramInfo) ; In ProgramInfo werden die Daten gespeichert
 
  Repeat
    len = D_GetOutput(@ProgramInfo,Mem)
    If len
      SetGadgetText(#Gadget_String,GetGadgetText(#Gadget_String)+PeekS(Mem,len))
    EndIf
  Until len = 0
 
  tmpstring.s = "netstat"+Chr(13)+Chr(10) ; !WICHTIG! CHR(10) muss vorkommen, sonst wird der Befehl nicht angenommen
  D_SendInputString(@ProgramInfo,tmpstring)
 
  Repeat
    len = D_GetOutput(@ProgramInfo,Mem)
    If len
      SetGadgetText(#Gadget_String,GetGadgetText(#Gadget_String)+PeekS(Mem,len))
      Received + len
    EndIf
  Until WaitWindowEvent() = #PB_Event_CloseWindow
 
  D_CloseProgram(@ProgramInfo)
Else
  MessageRequester("","Konnte Programm nicht ausführen!",16)
EndIf

FreeMemory(Mem)
Ich weiss jetzt aber nicht von wem der Codeschnipsel ist. Von mir ist er nicht.
Bild
Team100
Beiträge: 104
Registriert: 13.09.2004 22:59

Beitrag von Team100 »

... Umleiten von Konsolenfenstern ist ein Kapitel für sich.
Ich hab mich eine Zeit damit beschäftigt und habe herausgefunden:

- Die von MVXA gepostete Methode läuft bei statischen Konsolen-
ausgaben sehr gut bei allem was von CMD bzw. COMMAND (W98 +Co))
produziert wird, z.B. DIR, NET USE usw.

- Bei dynamischen Ausgaben wirds schon kritischer: Läßt man z.B. eine
Diskette formatieren wird es mit pipe nicht so ohne weiteres gelingen,
den %-Zähler (zählt von 0 bis 100) und die darauf folgenden Statuszeilen
ins eigene Programm zu übernehmen.

- Drittprogramme machen noch mehr Probleme, entweder wenn
dynamische Ausgaben vorhanden sind, oder manche liefern mit pipe
überhaupt nichts.

- 16-Bit Programme in der Dos-Box lassen sich grundsätzlich
nicht mit der pipe Methode umleiten.
Im Prinzip sollte es ja möglich sein, den Speicher des Anzeigefensters
auszulesen, bloß man kommt nicht an den entsprechenden Handles ...

Mir ist es nicht gelungen, eine Lösung dafür zu finden. Ich habe auch
andere Programmiersprachenforen nach Hinweisen untersucht, aber
außer den entsprechenden Fragen nach diesem Problem keine
Lösungen gefunden. API Code würde sich ja leicht auf PB übertragen
lassen.....

Ein Kasten Bier für denjenigen, der hier eine universelle Lösung zur Fernsteuerung
von 16-Bit Programmen findet (Eingabe - Ausgabe).... :mrgreen:

Wenn man Glück hat, lässt sich die Ausgabe des Konsolenprogramms durch
den >xxxxxx Parameter in eine Datei xxxxxx umleiten .....
Auf die Datei hat man dann Zugriff und kann mit Geschick sogar
dynamische Vorgänge auslesen.

Cu von Team100
Kompliziert kann es jeder lösen, aber das wirklich Geniale ist einfach.....
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

Wie wärs wenn wir einfach den Benutzer darum bitten den Text aus der Konsole in das Programm zu kopieren :mrgreen:? Scherz bei Seite. Eine universale Möglichkeit muss es doch geben. Immer hin kann man das ja in der orginal Konsole ja auch. Einen Textabschnitt markieren und dann kopieren. Zur Not könnten wir auch eine Mail an MS schicken.
Bild
Antworten