Startparameter zur Laufzeit durch erneutes starten ändern?



  • Hallo zusammen,

    ich würde gerne einem laufenden Programm einen Parameter übergeben. Zum Beispiel einen Dateinamen.
    Solange das Programm aus ist, kann ich die Startparameter nutzen, welche ich mit Hilfe von Environment.GetCommandLineArgs() abrufen kann. Das geht genau 1 Mal.

    Gibt es eine Möglichkeit, das Programm einfach ein zweites Mal "zu starten" um den Parameter zu ändern bzw. einen neuen zu übergeben? Bisher habe ich schon einmal eingebaut, dass man keine zweite Instanz des Programms aufrufen kann. Sonst habe ich irgendwann ja zig mal mein Programm laufen - das soll natürlich nicht sein.

    Jemand eine Idee dazu? Habe schon recht lange im Internet gesucht; Bin bisher aber nicht wirklich fündig geworden.

    Viele Grüße,
    Felix


  • Administrator

    Wieso willst du die Kommandozeilen-Argumente von deinen Programm ändern? Wieso änderst du nicht selbst die Einstellungen in deinem Programm? Wieso willst du dies so umständlich über die Kommandozeilen-Argumente tun?

    *völlig entgeistert flix anstarrt und nur noch etwas herausbekommt*
    Hääää?

    Grüssli



  • Stichwörter: Inter-Prozess Kommunikation, Sockets, Named Pipes, Shared Memory



  • Dravere schrieb:

    Wieso willst du die Kommandozeilen-Argumente von deinen Programm ändern? Wieso änderst du nicht selbst die Einstellungen in deinem Programm? Wieso willst du dies so umständlich über die Kommandozeilen-Argumente tun?

    *völlig entgeistert flix anstarrt und nur noch etwas herausbekommt*
    Hääää?

    Grüssli

    Ziel ist es, kein Verzeichnis mehr überwachen zu müssen, ob eine neue Datei vorhanden ist. Dabei wird sonst gemeldet, Datei vorhanden, aber in den meisten Fällen wird noch eine Weile geschrieben und man muss warten, bis diese fertig geschrieben ist.

    Per Kommandozeilenparameter möchte ich nun gerne das eigentliche Programm von einem anderen Programm aufrufen lassen. Mitgegeben wird ein Dateiname/Pfad nachdem diese Datei fertig geschrieben wurde. Das Ganze muss passieren, während das Programm läuft.

    O.o schrieb:

    Stichwörter: Inter-Prozess Kommunikation, Sockets, Named Pipes, Shared Memory

    Danke, schaue ich mir an.



  • Er will das (bzw. sowas ähnliches) machen, was die meisten Media-Player auch machen: wenn sein Programm gestartet wird, während es (eine andere Instanz davon) bereits läuft, dann möchte er der bereits laufenden Instanz eine Nachricht zukommen lassen, dass das Programm nochmal gestartet wurde + mit welchen Parametern.

    Zumindest glaube ich dass es das ist was er machen will 🙂


  • Administrator

    hustbaer schrieb:

    Zumindest glaube ich dass es das ist was er machen will 🙂

    Und wieso sagt er das nicht? 😃

    Dann könnte man auch so ein einfaches Beispiel präsentieren:

    using System;
    using System.IO;
    using System.IO.Pipes;
    using System.Threading;
    
    namespace SharpTest
    {
      class Program
      {
        static readonly string UniqueName = "{e718a3b3-2d19-40a4-bd2e-9b4f33a22f08}";
    
        static void Main(string[] args)
        {
          bool isNewMutex;
          var programMutex = new Mutex(true, UniqueName, out isNewMutex);
    
          if(isNewMutex)
          {
            Console.WriteLine("I'm the first!");
            Console.WriteLine("Waiting for the second...");
    
            using(var pipe = new NamedPipeServerStream(UniqueName, PipeDirection.In))
            {
              pipe.WaitForConnection();
    
              var input = new StreamReader(pipe);
              string msg = input.ReadLine();
    
              Console.WriteLine("Received message from the second: {0}", msg);
            }
          }
          else
          {
            Console.WriteLine("I'm the second!");
            Console.WriteLine("Sending \"Hello World!\" to the first one...");
    
            using(var pipe = new NamedPipeClientStream(".", UniqueName, PipeDirection.Out))
            {
              pipe.Connect();
    
              var output = new StreamWriter(pipe);
              output.AutoFlush = true;
    
              output.WriteLine("Hello World!");
    
              pipe.WaitForPipeDrain();
            }
    
            Console.WriteLine("Message sent.");
          }
    
          programMutex.Dispose();
    
          Console.ReadKey(true);
        }
      }
    }
    

    Mit entsprechenden Links zur Hilfestellung:
    http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
    http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.aspx
    http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeserverstream.aspx

    Grüssli



  • Dravere schrieb:

    hustbaer schrieb:

    Zumindest glaube ich dass es das ist was er machen will 🙂

    Und wieso sagt er das nicht? 😃

    Vermutlich weil er Anfänger ist und sich (noch) nicht besser ausdrücken kann 😉



  • hustbaer schrieb:

    Er will das (bzw. sowas ähnliches) machen, was die meisten Media-Player auch machen: wenn sein Programm gestartet wird, während es (eine andere Instanz davon) bereits läuft, dann möchte er der bereits laufenden Instanz eine Nachricht zukommen lassen, dass das Programm nochmal gestartet wurde + mit welchen Parametern.

    Zumindest glaube ich dass es das ist was er machen will 🙂

    Ja, im Grunde genommen richtig.

    Mein Programm läuft gerade. Dann wird es noch einmal, mit einem speziellen oder mit einem anderen oder neuen Parameter gestartet. Nun soll folgendes passieren: Das laufende Programm soll genau diesen Parameter zur weiterverarbeitung übergeben bekommen. Der zweite Aufruf darf aber keine wirkliche 2. Instanz des Programms öffnen sondern muss entweder das öffnen verhindern, oder sofort wieder schließen. Denn der Benutzer darf dieses eigentlich garnicht mitbekommen.

    Dravere schrieb:

    hustbaer schrieb:

    Zumindest glaube ich dass es das ist was er machen will 🙂

    Und wieso sagt er das nicht? 😃

    Dann könnte man auch so ein einfaches Beispiel präsentieren:
    Mit entsprechenden Links zur Hilfestellung:
    http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
    http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.aspx
    http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeserverstream.aspx

    Grüssli

    Super, Danke!

    hustbaer schrieb:

    Dravere schrieb:

    hustbaer schrieb:

    Zumindest glaube ich dass es das ist was er machen will 🙂

    Und wieso sagt er das nicht? 😃

    Vermutlich weil er Anfänger ist und sich (noch) nicht besser ausdrücken kann 😉

    Dachte, ich hätte es recht gut ausgedrückt. 😕 Naja egal, mit ein paar kleinen Umwegen habt Ihr ja verstanden, worum es geht. 👍



  • OK, nun bin ich auf ein Problem gestoßen.

    Ich nutze nun die Pipes. Zum Testen gibt es einfach ein kleines Windows Forms Programm. Da gibt es ein Fenster und einen Button.

    Was muss erreicht werden:
    - Programm startet -> Fenster geht auf
    - Pipe Client startet automatisch und sendet Parameter/Argumente
    - - Ist noch kein Server an (soll so sein) darf einfach nichts passieren
    - - - Ist dies die erste Instanz des Programms, passiert nichts weiter
    - - - Ist dies die zweite Instanz des Programms, darf nichts passieren, außer dass kein 2. Fenster auf geht und es quasi nach dem senden der Parameter direkt wieder aus ist.
    - Clickt der User den Button, startet der Server und wartet auf den Client.
    - - Das muss(!) nebenher passieren. das Programm muss ansonsten ganz Normal weiter arbeiten.
    - - Connected sich kein Client, kann der User alle Funktionen des Programms normal nutzen.
    - - Connected sich ein Client und sendet einen Parameter, muss intern eine Kleinigkeit ablaufen, der User kann dann normal weiter arbeiten.

    Was ist bisher erreicht:
    - Programm startet.
    Das wars schon fast... 🙄

    Also detailliert bedeutet das:
    Ich möchte das Programm starten. Gleichzeitig versuche ich den Client zu starten. Das geht aber nicht richtig, wenn kein Server läuft.
    Starte ich den Server zu erst, öffnet sich mein Fenster nicht mehr.

    Hier mein Code:
    Program.cs hat die Main-Methode - da startet nur Form1.

    Form1:

    namespace ParamTest
    {
        public partial class Form1 : Form
        {
            public string[] parameter; 
            public Form1()
            {
                InitializeComponent();
                PipeClient(Environment.GetCommandLineArgs());
            }
    
            private void btn_Params_Click(object sender, EventArgs e)
            {
                PipeServer();
            }
    
            public static void PipeClient(string[] args)
            {
                string client = "Client start. Arguments: " + args[1];
                Console.WriteLine(client);
                NamedPipeClientStream pipeClient =
                    new NamedPipeClientStream("localhost", "testpipe",
                    PipeDirection.InOut, PipeOptions.None,
                    TokenImpersonationLevel.Impersonation);
    
    			StreamWriter sw = new StreamWriter(pipeClient);
    			StreamReader sr = new StreamReader(pipeClient);
    			pipeClient.Connect();
    			sw.AutoFlush = true;
    
    			// Verify that this is the "true server"
    			if (sr.ReadLine() == "I am the one true server!")
    			{
    				sw.WriteLine(args[1]);
    			}
    			else
    			{
    				MessageBox.Show("Server could not be verified.");
    			}
    			pipeClient.Close();
            }
    
            public static void PipeServer()
            {
                NamedPipeServerStream pipeServer =
                new NamedPipeServerStream("testpipe", PipeDirection.InOut, 1);
                MessageBox.Show("NamedPipeServerStream thread created.");
    
                // Wait for a client to connect
                pipeServer.WaitForConnection();
                MessageBox.Show("Client connected");
                try
                {
                    StreamReader sr = new StreamReader(pipeServer);
                    StreamWriter sw = new StreamWriter(pipeServer);
                    sw.AutoFlush = true;
                    //Verify the server identity to the connected client
                    sw.WriteLine("I am the one true server!");
                    //get 1 argument from client
                    string filename = sr.ReadLine();
                    MessageBox.Show(filename);
                    //Server disconnect 
                    pipeServer.Disconnect();
                }
                catch (IOException ex)
                {
                    string exception = "ERROR: " +ex.Message;
                    MessageBox.Show(exception);
                }
            }
        }
    }
    

    Wenn ich durchsteppe kommt beim Erstellen von pipeClient folgendes: NumberOfServerInstances = "pipeClient.NumberOfServerInstances" hat eine Ausnahme vom Typ "System.InvalidOperationException" verursacht.
    Das kommt aber nirgendwo direkt als Fehler. Nur beim durchsteppen sichtbar ...

    Kann mir jemand ein wenig auf die Sprünge helfen in dem Bereich? Es muss wirklich wie oben beschrieben laufen.
    Ist das mit den Pipes nicht möglich, muss ich eine andere Lösung finden.

    Viele Grüße,
    Felix


  • Administrator

    Ohne deinen Code jetzt genauer anzuschauen, aber du hast gar keine Mutex eingesetzt. Durch einen Named-Mutex kannst du überprüfen, ob bereits ein Programm gestartet wurde und somit prüfen, ob ein Server vorhanden ist. Auch bietet Mutex eben die Möglichkeit an, einen Doppelstart zu verhindern.

    Grüssli



  • Ja stimmt, bisher habe ich Mutex nicht verwendet.
    Wenn ich einen Doppelstart durch Mutex verhindere, kann ich aber garnicht mehr einen neuen Parameter durch den erneuten "Start" des Programms übergeben. Oder habe ich etwas übersehen?

    Ich schaus mir auf jeden Fall mal etwas genauer an.

    Viele Grüße



  • hä? klar geht das dann "noch" (es geht nur so)

    mutex m("lalala");
    
    if (kann_mutex_locken(m))
        lauf_normal();
    else
        schicke_parameter_an_andere_instanz_und_beende_dich();
    

    natürlich kannst du auch das vorhanden-sein/nicht-vorhanden-sein des pipe-servers als indikation für "läuft schon" verwenden.


Anmelden zum Antworten