[WPF] Named Pipes - Daten kommen nicht an / werden nicht gesendet.

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von LuaX.

    [WPF] Named Pipes - Daten kommen nicht an / werden nicht gesendet.

    Ich versuche gerade mit Mutext eine Einzelinstanzanwendung mit C# und WPF zu machen.
    Das mit der Einzelinstanz funktioniert zwar. Allerdings soll wenn eine 2. Instanz gestartet wird die Erste instanz in
    den vordergrund geholt werden.

    Ich habe dazu zwei Debuginstanzen gestartet, die erste verhielt sich wie gesollt, die zweite jedoch bleibt bei meiner Send(String)-methode in meiner Klasse
    PipeConnection stecken, der dortige erste Haltepunkt wird erreicht, der zweite aber nicht.

    Da ich ratlos bin, und nich weis was ich tun soll wende ich mich nun an euch.

    Hier ist dann mal der Quellcode der Startroutine:

    C#-Quellcode

    1. MUTEX = new Mutex(true, "PGMA", out bool IsNewInstance);
    2. if (!IsNewInstance)
    3. {
    4. PipeConnection pcon = new PipeConnection();
    5. if (pcon.Connect())
    6. {
    7. pcon.Send("pp:activate"); //Bis hierhin wird in der zweiten instanz ausgeführt.
    8. }
    9. else throw new Exception("KANN NICHT VERBINDEN");
    10. App.Current.Shutdown();
    11. return;
    12. }
    13. if(PipeServer.Start() != true)
    14. {
    15. MessageBox.Show("SCHWERWIEGENDER FEHLER!");
    16. }


    Und die helferklassen:
    Spoiler anzeigen

    C#-Quellcode

    1. public class PipeConnection
    2. {
    3. protected StreamReader READER { get; set; }
    4. protected StreamWriter WRITER { get; set; }
    5. protected NamedPipeClientStream STREAM { get; set; }
    6. protected bool RUNNING { get; set; } = false;
    7. public bool Connect()
    8. {
    9. try
    10. {
    11. NamedPipeClientStream str = new NamedPipeClientStream("PPCP");
    12. str.Connect(100);
    13. READER = new StreamReader(str);
    14. WRITER = new StreamWriter(str);
    15. return RUNNING = true;
    16. } catch
    17. {
    18. return RUNNING = false;
    19. }
    20. }
    21. public void Disconnect()
    22. {
    23. STREAM?.Close();
    24. STREAM?.Dispose();
    25. RUNNING = false;
    26. }
    27. public void Send(String data)
    28. {
    29. Debugger.Break();
    30. WRITER.WriteLine(data+"\n");
    31. WRITER.Flush();
    32. Debugger.Break();
    33. }
    34. }


    C#-Quellcode

    1. public static class PipeServer
    2. {
    3. /// <summary>
    4. /// This is the Server itself.
    5. /// </summary>
    6. private static NamedPipeServerStream PIPE;
    7. private static StreamReader READER;
    8. private static StreamWriter WRITER;
    9. private static bool CONNECTED = false;
    10. /// <summary>
    11. /// Handler for internal commands like pp:version
    12. /// </summary>
    13. /// <returns>The answer or null if the command is not an internal one.</returns>
    14. private static String HandleInternal(String arrivedData)
    15. {
    16. switch(arrivedData)
    17. {
    18. // Returns the version
    19. case "pp:version":
    20. return Assembly.GetExecutingAssembly().GetName().Version.ToString();
    21. // Returns weather this build targets 'debug' or not.
    22. case "pp:isDebugBuild":
    23. #if DEBUG
    24. return "true";
    25. #else
    26. return "false";
    27. #endif
    28. //Pushes the window to foreground and returns 'ok'
    29. case "pp:activate":
    30. App.Current.MainWindow.Activate();
    31. return "ok";
    32. default:
    33. return null;
    34. }
    35. }
    36. public static bool Start()
    37. {
    38. if(!CONNECTED)
    39. {
    40. try
    41. {
    42. PIPE = new NamedPipeServerStream("PacksPlayCommunicationPipe");
    43. READER = new StreamReader(PIPE);
    44. WRITER = new StreamWriter(PIPE);
    45. CONNECTED = true;
    46. Task.Factory.StartNew(() =>
    47. {
    48. while(CONNECTED)
    49. {
    50. String arrived = READER.ReadLine();
    51. MessageBox.Show("Daten angekommen: " + arrived);
    52. String answer = null;
    53. if(arrived.StartsWith("pp:"))
    54. {
    55. answer = HandleInternal(arrived);
    56. }
    57. if(answer==null)
    58. {
    59. DataArrived(new PipeServerDataArrivedEventArgs(arrived, WRITER));
    60. } else
    61. {
    62. WRITER.Write(answer);
    63. }
    64. }
    65. });
    66. return true;
    67. } catch
    68. {
    69. return false;
    70. }
    71. }
    72. return true;
    73. }
    74. public delegate void PipeServerDataArrived(PipeServerDataArrivedEventArgs evtArgs);
    75. public static event PipeServerDataArrived DataArrived;
    76. }
    77. public class PipeServerDataArrivedEventArgs : EventArgs
    78. {
    79. public String ArrivedData { get; }
    80. public StreamWriter AnswerStream { get; }
    81. public PipeServerDataArrivedEventArgs(String DataArrived, StreamWriter Writer)
    82. {
    83. ArrivedData = DataArrived;
    84. AnswerStream = Writer;
    85. }
    86. }
    87. [/spoiler][spoiler]

    ( Ja mein "Methoden-Beschreibungs-Englisch" ist nicht das beste)

    Wäre "voll doll" wenn ihr mir sagen könntet was an diesem Code nicht stimmt.

    Grüße,
    Luca
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.

    LuaX schrieb:

    Allerdings soll wenn eine 2. Instanz gestartet wird die Erste instanz in den vordergrund geholt werden.
    C# oder VB.NET :?:
    Dein Titel und Dein Code widersprechen sich.
    =====
    Innerhalb des Skops des Mutex' hat Pipe-Code nix zu suchen. Dafür könntest Du Dir eine static Prozedure in Deine MainForm bauen.
    Der Rest geht ganz easy:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Diagnostics;
    3. using System.Runtime.InteropServices;
    4. using System.Threading;
    5. using System.Windows.Forms;
    6. namespace DeviceControl
    7. {
    8. static class Program
    9. {
    10. [DllImport("User32.dll")]
    11. [return: MarshalAs(UnmanagedType.Bool)]
    12. static extern bool SetForegroundWindow(IntPtr hWnd);
    13. [DllImport("User32.dll")]
    14. [return: MarshalAs(UnmanagedType.Bool)]
    15. static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    16. //----------------------------------------------------------
    17. /// <summary>Der Haupteinstiegspunkt für die Anwendung.</summary>
    18. [STAThread]
    19. static void Main()
    20. {
    21. Application.EnableVisualStyles();
    22. Application.SetCompatibleTextRenderingDefault(false);
    23. bool isFirstInstance;
    24. // Please use a unique name for the mutex to prevent conflicts with other programs
    25. using (Mutex mtx = new Mutex(true, "Application Test", out isFirstInstance))
    26. {
    27. if (isFirstInstance)
    28. {
    29. Application.Run(new MainForm());
    30. }
    31. else
    32. {
    33. // The application is already running
    34. // TODO: Display message box or change focus to existing application instance
    35. MessageBox.Show("Application already running!", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
    36. Process current = Process.GetCurrentProcess();
    37. foreach (Process process in Process.GetProcessesByName(current.ProcessName))
    38. {
    39. if (process.Id != current.Id)
    40. {
    41. // Fenster des Prozesses in den Vordergrund holen
    42. Program.SetForegroundWindow(process.MainWindowHandle);
    43. Program.ShowWindowAsync(process.MainWindowHandle, 9);
    44. break;
    45. }
    46. }
    47. }
    48. } // releases the Mutex
    49. }
    50. }
    51. }
    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 schrieb:

    C# oder VB.NET

    Oh sorry, habe vergessen dazuzusagen das es sich um eine WPF-Anwendung handelt und der Startcode im "Application.Startup" Event ausgeführt wird.

    ErfinderDesRades schrieb:

    ich versteh garnet, was named Pipes mit einer Single-Instance-Anwendung zu tun haben.


    Also die mögliche Zweite instanz soll, wenn sie keine Argumente hat, die erste instanz in den Vordergrund holen. Und wenn sie aber Startargumente hat, soll sie diese dann eben über diese Pipe an die bereits laufende Instanz senden damit diese die "Argumente bearbeiten kann" (Das mit den argumenten ist noch nicht implementiert)

    Grüße
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.
    kommt mir sehr aufwändig vor, dafür extra einen NamedPipe-Listener einzurichten.
    Aber es gibt tatsächlich Leuts, die das als Vorgehensweise propagieren.

    wie dem auch sei:
    in vb.net habich mal NamedPipe-Kommunikation zum Laufen gebracht - aber als Chat, nicht fürs SingleApping: VersuchsChat mit leistungsfähigem Server

    in c# habich von irgendwo eine SingleApp-Solution gedownd, die sogar einen TcpChannel dafür einsetzt 8| !
    wolle habe diese?
    So bin wieder lebendig.
    Ich schau mir deinen "Chat" an, und überlege wo der Fehler liegen könnte.

    Grüße.
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.