Anonyme Pipes unter VB.NET richtig anwenden!

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Anonyme Pipes unter VB.NET richtig anwenden!

    Moin! :)
    Erstmal möchte ich mich entschuldigen, weil ich in letzter Zeit viele neue Beitrage geöffnet habe.
    Und nicht das Forum zu spammen möchte.
    Wie ihr vielleicht schon wisst, möchte ich den Inhalt aus einer Listbox einer fremden Anwendung ausgelesen werden.
    Gestern habe ich den Begriff „Anonyme Pipes“ kennen gelernt.
    Und das könnte die Lösung meines Problems sein.
    Leider habe ich wenig Infos gefunden, nur ein Projekt in C#.
    Als ich dieses umschreiben wollte in VB.NET komme ich nicht weiter…
    Ich habe den Client bereits in VB.NET umgeändert.
    Beim Server habe ich das Problem, es sind 3 Zeilen, die mir das Leben schwer machen.
    Freue mich auf eure Hilfe!
    BIG THX

    Bilder.







    Projekte im Anhang!
    Altes VB.NET Projekt gelöscht, C# Code noch verfürgbar!

    PipesServerTestC#.zip
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Cheffboss“ ()

    Die +=-Sachen, wo bei dir Fehler angezeigt werden, sid eigentlich AddHandler-Aufrufe. In C# sind die beide += und der Converter kann das nicht unterscheiden.

    Edit: Und ​-= ist im Event-Kontext ​RemoveHandler.
    @nafets
    Danke, für deine Antwort.
    Jetzt könnte ich die zwei Fehler los werden.
    Aber wie ich den dritten Fehler los bekomme, weiß ich noch nicht!? ?(

    VB.NET-Quellcode

    1. '_pipeServer.PipeMessage += New DelegateMessage(AddressOf PipesMessageHandler)
    2. AddHandler _pipeServer.PipeMessage, New DelegateMessage(AddressOf PipesMessageHandler)


    VB.NET-Quellcode

    1. ' _pipeServer.PipeMessage -= New DelegateMessage(AddressOf PipesMessageHandler)
    2. AddHandler _pipeServer.PipeMessage, New DelegateMessage(AddressOf PipesMessageHandler)



    Fehlerzeile:

    VB.NET-Quellcode

    1. PipeMessage.Invoke(stringData)
    Visual Basic.NET 8o
    MS-SQL
    8o
    Mach da mal einfach das .Invoke weg und schau, ob das dann funktioniert. Das ist ein Delegatenaufruf, den man in C# mit ​.Invoke() machen kann, wobei das dort optional ist. Ich nehme jetzt mal an, dass das in VB.NET wohl nur ohne das ​.Invoke geht.
    @nafets
    Vielen Dank, ich habe es nun soweit geschaft.
    Das Projekt für alle Im Anhang zum runterladen...
    Das einzige was schade ist, das man im Debugger-Modus ausirgendeinen Grund,
    keine Daten in die Listbox eintragen kann.
    Wer den Code optimieren will gerne...

    VB.NET-Quellcode

    1. Private Sub _pipeServer_NeueDateien(wert As String) Handles _pipeServer.NeueDateien
    2. If Debugger.IsAttached Then
    3. MsgBox("nicht im debuger!")
    4. Else
    5. Me.ListBox1.Items.Add(wert)
    6. End If
    7. End Sub



    edit2:
    Da der Code noch nicht gut war und noch ein Fehler drin ist, habe ich diesen wieder gelöscht!
    Die neue Version folgt!
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Cheffboss“ ()

    Hallo,
    was willst du mit Pipes?
    Du kannst vielleicht eine rauchen, aber nicht damit in Windows programmieren.
    Pipes sind Interprozess-Connections und Du wirst damit nie bis gar nie was zu tun haben.

    Wenn Du Listboxen fremder Programme auslesen willst must du trotzdem etwas tun.
    Du musst ermitteln zu welchem Window die Listbox gehört.
    Hast Du das Handle zu diesem Window kannst Du es subclassen oder es nach seinen
    Childs durchsuchen. Die Listbox hat die Klasse: Listbox (wer hätte das gedacht ).
    Aber dieses Windwo könnte viele solcher Klassen als Childs haben - welches ist
    nun deins?

    Out of Memory schrieb:

    aber nicht damit in Windows programmieren.
    Pipes sind Interprozess-Connections und Du wirst damit nie bis gar nie was zu tun haben.
    Eh, doch. Schaust Du in seine anderen Threads. Er hat 2 Programme, bei denen er einen Weg gesucht hat, wie die beiden miteinander reden können. Ohne TCP/IP. Auf dem selben PC. Ohne Datenbank. Ohne Dateien. Mach einen Gegenvorschlag, wie man sowas noch besser lösen kann. Ohne Pipes. Und ohne fremde Prozesse auszulesen. Weil: Das ist, wenn es eben gar nicht mehr anders geht.

    ##########

    @Cheffboss: Der VB6-Namespace ist bei Dir wohl nicht rauszukriegen oder? Und Option Strict Off kann man auch in den Projekteigenschaften einstellen, dann musst Du es nicht in jede Datei einzeln schreiben.
    Zum Debugger-Problem:

    VB.NET-Quellcode

    1. Private Sub _pipeServer_NeueDateien(wert As String) Handles _pipeServer.NeueDateien
    2. Me.Invoke(Sub() Me.ListBox1.Items.Add(wert.Replace(Microsoft.VisualBasic.vbNullChar, Nothing)))
    3. End Sub

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Höhö, da haste recht. Also, dass hier n Beispiel mit NamedPipes gegeben wurde.

    ErfinderDesRades schrieb:

    was immer das auch sein mag
    Hmm … ne Pipe ohne Namen? Daher auch nur PC-lokal nutzbar.
    Dann hier was mit anonymen auf Konsole.
    Die entstehende PipeClient.Exe muss im selben Verzeichnis sein wie die PipeServer.Exe. Kann man natürlich auch (im Code) ändern.
    Achtung, unidirektional:
    Server

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.IO.Pipes
    3. Module Module1
    4. Sub Main()
    5. Call New PipeServer().Main()
    6. End Sub
    7. End Module
    8. Friend Class PipeServer
    9. Private ReadOnly PipeClientProcess As New Process
    10. Friend Sub Main()
    11. Using PipeServer As New AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable)
    12. PrepareClientApp(PipeServer)
    13. CommunicateWithClient(PipeServer)
    14. End Using
    15. TerminateConnection()
    16. End Sub
    17. Private Sub PrepareClientApp(PipeServer As AnonymousPipeServerStream)
    18. PipeClientProcess.StartInfo.FileName = "pipeClient.exe" 'die PipeClient.Exe muss daher im selben Verzeichnis sein wie die PipeServer.Exe
    19. PipeClientProcess.StartInfo.Arguments = PipeServer.GetClientHandleAsString()
    20. PipeClientProcess.StartInfo.UseShellExecute = False
    21. PipeClientProcess.Start()
    22. PipeServer.DisposeLocalCopyOfClientHandle()
    23. End Sub
    24. Private Sub CommunicateWithClient(PipeServer As AnonymousPipeServerStream)
    25. Try
    26. Using StreamWriter As New StreamWriter(PipeServer)
    27. StreamWriter.AutoFlush = True
    28. StreamWriter.WriteLine("SYNC")
    29. PipeServer.WaitForPipeDrain()
    30. Do
    31. Console.Write("[SERVER] Enter text: ")
    32. StreamWriter.WriteLine(Console.ReadLine())
    33. PipeServer.WaitForPipeDrain()
    34. Loop
    35. End Using
    36. Catch IOEx As IOException
    37. Console.WriteLine("[SERVER] Error: {0}", IOEx.Message)
    38. End Try
    39. End Sub
    40. Private Sub TerminateConnection()
    41. PipeClientProcess.WaitForExit()
    42. PipeClientProcess.Close()
    43. PipeClientProcess.Dispose()
    44. End Sub
    45. End Class

    Client

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.IO.Pipes
    3. Module Module1
    4. Sub Main(CommandLineArguments As String())
    5. Call New PipeClient().Main(CommandLineArguments)
    6. WaitForInput()
    7. End Sub
    8. Private Sub WaitForInput()
    9. Console.Write("[CLIENT] Press Enter to continue …")
    10. Console.ReadLine()
    11. End Sub
    12. End Module
    13. Friend Class PipeClient
    14. Private PipeClient As AnonymousPipeClientStream = Nothing
    15. Private StreamReader As StreamReader = Nothing
    16. Public Sub Main(CommandLineArguments As String())
    17. PossiblyCreatePipeClientWith(CommandLineArguments)
    18. RunPipeInputLoop()
    19. End Sub
    20. Private Sub PossiblyCreatePipeClientWith(CommandLineArguments As String())
    21. If CommandLineArguments.Count = 0 Then Return
    22. PipeClient = New AnonymousPipeClientStream(PipeDirection.In, CommandLineArguments(0))
    23. End Sub
    24. Private Sub RunPipeInputLoop()
    25. If PipeClient Is Nothing Then Return
    26. CreateStreamReader()
    27. ReportStatus()
    28. ReportAndWaitForServerData()
    29. ProcessPipeData()
    30. DestroyStreamReader()
    31. DestroyPipeClient()
    32. End Sub
    33. Private Sub CreateStreamReader()
    34. StreamReader = New StreamReader(PipeClient)
    35. End Sub
    36. Private Sub ReportStatus()
    37. Console.WriteLine("[CLIENT] Current TransmissionMode: {0}.", PipeClient.TransmissionMode)
    38. End Sub
    39. Private Sub ReportAndWaitForServerData()
    40. Do
    41. Console.WriteLine("[CLIENT] Wait for sync...")
    42. Loop Until StreamReader.ReadLine() = "SYNC"
    43. End Sub
    44. Private Sub ProcessPipeData()
    45. Do
    46. Dim IncomingData = StreamReader.ReadLine()
    47. If IncomingData Is Nothing OrElse IncomingData = "" OrElse IncomingData = "Quit" Then Exit Do
    48. Console.WriteLine("[CLIENT] Echo: " & IncomingData)
    49. Loop
    50. End Sub
    51. Private Sub DestroyStreamReader()
    52. StreamReader.Dispose()
    53. StreamReader = Nothing
    54. End Sub
    55. Private Sub DestroyPipeClient()
    56. PipeClient.Dispose()
    57. PipeClient = Nothing
    58. End Sub
    59. End Class

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @an alle
    Ich habe ein neues Problem und verstehe es einfach nicht. ;(
    Ich arbeite mit Anonyme Pipes, so weit geht alles ganz gut.
    Aber wenn ich den String mit „Path.GetFileName“ verarbeiten möchte, kommt folgender Fehler: „Illegales Zeichen im Pfad.“.
    Ich habe mir zuerst den Client angeschaut, dieser sendet alles ganz ok.
    Dann bin ich auf die Idee gekommen, dass es vielleicht ein Converterproblem ist, deshalb habe ich da alles ausprobiert(UTF8, UNICODE, ANSI).
    Diese habe ich beim Server und Client beider seitig ausprobiert!
    Ich habe den String der empfangen wurden ist, mit Notepad ++ untersucht, dort findet man kein verbotenes/versteckte Zeichen.
    Wenn ich im Event „NeueDateien“ bin und den Wert in die Listbox1 einfüge geht es....
    Aber sobald ich System.IO.Path.GetFileName(wert) verwende, kommt diese Fehlermeldung!
    Das Projekt habe ich hochgeladen, freue mich wenn mir jemand sagen kann, warum das Problem da ist, und vorallem wie ich es lösen kann.
    BIG THX

    VB.NET-Quellcode

    1. Private Sub pipeServer_NeueDateien(wert As String) Handles pipeServer.NeueDateien
    2. Dim test() As String = wert.Split(CType("|", Char()))
    3. Me.ListBox1.Items.Add(test(1)) ' <----- So gehts... Warum?
    4. Me.ListBox1.Items.Add(System.IO.Path.GetFileName(test(1))) ' <----- Fehlerquelle!
    5. End Sub


    Projekt:
    Bug Projekt gelöscht - unten die neue Version!
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cheffboss“ ()

    @Cheffboss Machst Du zunächst:

    VB.NET-Quellcode

    1. Dim test() As String = wert.Split("|"c)
    Und dann gibst Du mal aus, was in test(1) drinne steht.
    Ich denke mal, dass Du dann sofort siehst, warum der Fehler kommt.
    Lerne, Dein Programm zu debuggen!
    Debuggen, Fehler finden und beseitigen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Danke, aber leider ist der Bug noch vorhanden....

    edit2
    Super, Vielen Dank.

    edit3:
    @an alle
    @RodFromGermany
    Danke, ich könnte das Problem nun lösen. :)
    Im Anhang befindet sich der Code.
    Einfach nur dies verändert und es läuft perfekt...

    VB.NET-Quellcode

    1. Dim stringData As String = Encoding.UTF8.GetString(buffer, 0, buffer.Length).Replace(vbNullChar, "")


    Projekt:
    Anonyme Pipes -VB.NET.zip (geupdatet...)
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Cheffboss“ ()

    @Cheffboss OHa, da kam ein C-String an, dwe wird mit einem 0-Char beendet.
    Das kannst Du auchg mit einem .TrimEnd("0"c) erledigen, das ist übersichtlicher.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @ErfinderDesRades Glückwunsch, gefunden. :thumbsup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!