6 Stimmen

Umleitung von nativen dll stdout/stderr aus C#

Ich versuche, die Ausgabe eines Drittanbieters nativen dll umleiten, die Ausgaben zu stdout/stderr von innerhalb von C#. Die Ausgabe von stdout und stderr sollte in eine Protokolldatei gehen.

Hier ist meine Idee (x2 für zwei Streams):

  • Erstellen einer AnonymousPipeServerStream
  • Holen Sie sich den Griff des Rohrs über _outServer.SafePipeHandle.DangerousGetHandle()
  • Verwenden Sie P/Invoke zum Aufrufen von SetStdHandle mit besagtem Griff
  • Erstellen einer AnonymousPipeClientStream mit dem Server-Stream verbunden
  • Erstellen Sie einen Thread, der in einer Schleife aus der Datei AnonymousPipeClientStream und die Ausgabe an den Logger.
  • Regelmäßig anrufen flush über die AnonymousPipeServerStream

All dies scheint also gut zu funktionieren... innerhalb meines Codes. Sobald die Kontrolle an die native DLL übergeben wird, geht alles zurück zu stderr! Wenn es nötig ist, kann ich in der nativen DLL debuggen und sehen, was falsch läuft, aber... Ich würde wirklich lieber nicht, also hat jemand eine Idee, bevor ich 10 Stunden damit verbringe, herauszufinden, wie Griffe funktionieren?

Als Referenz finden Sie den Testcode unter: http://pastebin.com/f3eda7c8 . Das Interessante sind die Zeilen 58-89 im Konstruktor. (Ich werde die Fehlerbehandlung usw. natürlich später hinzufügen).

0 Stimmen

Der Code auf pastebin.com scheint einige Fehler zu haben. Z.B. wird der Zeichenpuffer "_buffer" in zwei Threads verwendet...

0 Stimmen

@Stiefel - Ups, ja, das stimmt. Ich habe das ziemlich schnell zusammengeworfen, IIRC.

3voto

Robert Fraser Punkte 10267

Ich habe es gelöst, obwohl die Lösung (natürlich) nur wenig mit dem Problem zu tun hat. Die dll wurde in mingw kompiliert, die anscheinend nicht respektieren die Handles von der MSVC-Laufzeit verwendet.

Ich werde den Code und die Lösung oben lassen, falls jemand anderes auf dieses Problem stößt.

0 Stimmen

Also gibt es eine Möglichkeit, diese Arbeit zu machen, wenn in eine MnGW kompilierte Dll von C# aufrufen? Funktioniert Ihre Pastebin-Lösung oder gibt es etwas anderes?

0voto

eugen_nw Punkte 117

Verwenden Sie den Code unter https://pastebin.com/f3eda7c8 Ich habe es unter Windows 10 und in einem Windows LTSC 2019 Container zum Laufen gebracht. Allerdings erfasst es nur die Konsolenausgabe des C#-Codes, nicht eine Spur von der nicht verwalteten DLL printf-Ausgabe, die das Ergebnis, das ich zu erreichen wünschen ist. Ich musste den Hack unten nach den SetStdHandle-Zuweisungen verwenden, um es zu bekommen, arbeiten - ein Hack, die ich nicht wirklich mag BTW.

Könnte jemand bitte mich aufklären, was fehlt für mich, um es zu bekommen, um die printf-Ausgabe an die Konsole umzuleiten, die aus der nativen DLL stammt? Muss ich ein fflush(stdout / stderr) nach jeder [f]printf Aussage? Oder einfach fflush(stdout); y fflush(stderr); bevor die Funktion, an deren Ausgabe ich interessiert bin, zurückkehrt? In der Tat habe ich eine Reihe von fflush(stdout); Aufrufe nach Zeilen, die ich in der Ausgabe des Containers sehe, aber keine dieser nativen printf Informationen wurden umgeleitet.

        private void _ResetConsoleOutStream()
        {
            //Force console to recreate its output stream the next time Write/WriteLine is called
            typeof(Console).GetField("_out", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
                           .SetValue(null, null);
        }```

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X