Laden...

Via cmd Befehl in laufendes Programm schreiben

Erstellt von DannyDzWare vor 2 Jahren Letzter Beitrag vor 2 Jahren 320 Views
D
DannyDzWare Themenstarter:in
5 Beiträge seit 2022
vor 2 Jahren
Via cmd Befehl in laufendes Programm schreiben

Hallo zusammen und Guten Abend,

ich bin erneut auf der Suche nach einer Gedankenstütze. Ich habe bereits einige Zeit dem Googeln gewidmet, bisher aber ohne Erfolg. Ich schätze aber, es liegt daran, dass ich nicht genau weiß, wonach ich suche. Ok, das klingt witzig. Ich versuche mal zu erklären, wonach ich suche:

Ich habe folgende Herausforderung: Ich verwende ein Programm, dass in der Ausführung einen vereinfachten Codeeditor besitzt. Mit diesem ist es immerhin möglich, dass man via Run Befehl ein Programm mit Argumenten starten kann. Ich habe ein eigenes Programm geschrieben, was ein paar Funktionen ergänzt. Bisher nutze ich aber die umständliche Möglichkeit, dass ich Befehle in eine Textdatei schreibe, die dann wiederum von meinem Programm ausgelesen werden. Ich würde es lieber haben, dass ich quasi mein Programm starte und dann via cmd Befehl direkt in das offene Programm auf Variablen schreiben bzw. Ereignisse auslösen kann. Z.B. MeinProgramm -StarteProgramm1 -Variable2:IrgendeinWert
Welche Möglichkeit habe ich? Wonach muss ich gezielter Suchen?
Ist es überhaupt möglich?

Wie gesagt, die Herausforderung ist, dass das verwendete Programm eigentlich keine Möglichkeiten bereitstellt mit der Außenwelt zu kommunizieren.
Vielen Dank für eure Hilfe. Wenn ihr weiterführende Fragen habt, lasst es mich bitte wissen.

Liebe Grüße
Daniel Dzierzon

P
57 Beiträge seit 2017
vor 2 Jahren

Hallo,

wenn es sich um eine Konsolenapplikation dreht, dann nutze doch Command Line Args aus der Main-Methode dafür.

Du kannst das auch auf andere Applikationstypen (Winforms, WPF etc.) recht leicht adaptieren.

Gruß 🙂

.....an unhandled exception is the first way to think about your pattern of programming....
.....nur weil ich nicht weiß was dort passiert, bedeutet es nicht, dass ich nicht weiß, wie man es lösen kann - aber das ist wahrscheinlich....

D
DannyDzWare Themenstarter:in
5 Beiträge seit 2022
vor 2 Jahren

Hi Platoon, vielen Dank für die Antwort.
Dabei fiel mir auf, dass ich total vergessen habe, zu sagen, was ich nutze. Mein Programm ist eine Windows Form.
Dass mit den Command Line Args ist mir ein bisschen geläufig.
Ich habe es geschafft, dass das Programm gestartet werden kann mit Argumenten. Das funktioniert sehr gut.
Das Problem was ich gerade sehe, ist, dass ich damit ja immer wieder ein "neues" Programm Aufrufe.
Wie muss ich es schreiben, dass diese Argumente in das bereits offene Programm einfließen?

Danke nochmal für die Antwort.
Schönen Abend noch.

2.078 Beiträge seit 2012
vor 2 Jahren

Wie muss ich es schreiben, dass diese Argumente in das bereits offene Programm einfließen?

Das ist deutlich komplexer 🙂

Es gibt verschiedene Wege, der heute vermutlich einfachste Weg (weil es sehr gutes Tools gibt) wäre eine Web-API, die Du aus deinem ominösen Skript-Programm heraus aufrufst.

F
10.010 Beiträge seit 2004
vor 2 Jahren

Ist eigentlich nicht so schwer.

Es gibt im Namespace Microsoft.VisualBasic die Klasse https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.applicationservices.windowsformsapplicationbase?view=windowsdesktop-6.0
Wenn du deine Program Klasse davon ableitest, bekommst du z.b. die überschreibbare Methode OnStartupNextInstance
Siehe what-is-the-correct-way-to-create-a-single-instance-wpf-application/19326#19326
Die frage ist zwar über WPF, aber als das "erfunden" wurde gab es WPF noch garnicht

D
261 Beiträge seit 2015
vor 2 Jahren

Suchst du vielleicht eine REPL (Read-Eval-Print-Loop)?
Also eine Schleife (Loop), in der du immer wieder Eingaben vom Benutzer abfragen kannst (Read), diese verarbeitest (Eval) und anschließend das Ergebnis ausgibst (Print).

D
DannyDzWare Themenstarter:in
5 Beiträge seit 2022
vor 2 Jahren

Guten Morgen,
danke für die vielen Antworten bereits. Ich muss sagen, dass ich die Verlinkung, die FZelle gegeben hat, sehr hilfreich schon finde.
Ich habe das jetzt schon mal in ein neues Testprogramm integriert. Es sieht so aus:

Klasse NativeMethods.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Testen
{
    internal class NativeMethods
    {
        public const int HWND_BROADCAST = 0xffff;
        public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
        [DllImport("user32")]
        public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
        [DllImport("user32")]
        public static extern int RegisterWindowMessage(string message);

        public static string[] Argumente;
    }
}

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Testen
{
    internal static class Program
    {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
       
        [STAThread]
        static void Main(string[] args)
        {
            string[] CommandLineArgs;
            if (mutex.WaitOne(TimeSpan.Zero, true))
            {
                CommandLineArgs = Environment.GetCommandLineArgs();
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form2(CommandLineArgs));
                mutex.ReleaseMutex();
            }
            else
            {
                // send our Win32 message to make the currently running instance
                // jump on top of all the other windows
               CommandLineArgs = Environment.GetCommandLineArgs(); //Hier werden nochmal die Argumente abgefragt
                NativeMethods.Argumente = CommandLineArgs;
                MessageBox.Show("Test " + CommandLineArgs[1]);
                NativeMethods.PostMessage(
                    (IntPtr)NativeMethods.HWND_BROADCAST,
                    NativeMethods.WM_SHOWME,
                    IntPtr.Zero,
                    IntPtr.Zero);
            }
        }
    }
}

Die eigentliche Form Form2.cs


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Testen
{
    public partial class Form2 : Form
    {
        public string[] parameter;
        public Form2(string[] args)
        {
            parameter = args;
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            if(parameter.Length > 1)
            {
                this.Text += parameter[1];
            }
        }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == NativeMethods.WM_SHOWME)
            {
               parameter = NativeMethods.Argumente;
               MessageBox.Show(parameter[1].ToString()); 
                
                ShowMe();
                if (parameter != null && parameter.Length > 1)
                {
                    this.Text = parameter[1];
                }
            }
            base.WndProc(ref m);
        }
        private void ShowMe()
        {
            if (WindowState == FormWindowState.Minimized)
            {
                WindowState = FormWindowState.Normal;
            }
            // get our current "TopMost" value (ours will always be false though)
            bool top = TopMost;
            // make our form jump to the top of everything
            TopMost = true;
            // set it back to whatever it was
            TopMost = top;
        }
    }
}


Was das Programm bisher macht ist, dass es beim ersten Aufruf startet und der Wert unter parameter[1] wird dem Form Titel Text hinzugefügt. Das funktioniert einwandfrei.
Wenn ich das Programm ein weiteres Mal starte mit einem anderen Argument[1], dann erscheint auch brav die "Messagebox" mit "Test xxxx" und danach "Es läuft doch schon" und dann wird aber der Titel nicht geändert. Ich hatte es vorher etwas anders gehabt, da sagte es mir, dass die Variable parameter = null ist. Wenn ich so drüber nachdenke, ist es ja auch logisch, weil ich ja quasi zwei Programme betrachten muss. Und das eine bekommt nicht die Variable, die in dem anderen Programm gesetzt wird. Das 2. Programm hat lediglich die Info, ob ein gleiches Programm bereits läuft.
Jetzt stehe ich aber auf dem Schlauch. Wie kann ich denn die argumente aktualisieren? Also, dass die Argumente von Programm 2 in das bereits offene Programm gelangen?
Ich hätte daran gedacht, dass er unter dem void WndProc wieder neu ausgewertet werden muss, leider weiß ich nicht, wie ich das hinkriege.

Könnt ihr mir da nochmal helfen bitte.

Vielen Dank auf jeden Fall für euer Feedback. Das hilft mir sehr und Danke auch für die Gedankenstütze, sodass ich schon mal auf dem richtigeren Weg bin.

Liebe Grüße
Daniel

4.931 Beiträge seit 2008
vor 2 Jahren

Hallo,

in "Nur eine Instanz pro Anwendung" featuring IPC gibt es dafür eine Klasse, welche das kapselt.
Und auf Seite 2 habe ich dafür eine aktualisierte und verbesserte Version zur Verfügung gestellt (du müßtest dort nur einen Account anlegen, um die Anhänge zu sehen).
Mittels des Delegat OnAddArgs werden dann die neuen Parameter übergeben.

In deinem Code müßtest du ja mittels des Broadcast die Parameter an die andere (Haupt)Anwendung senden (und gerade das ist ja der entscheidende Teil der Inter-Process-Communication [IPC]).

F
10.010 Beiträge seit 2004
vor 2 Jahren

Was hat das mit dem zu tun was ich verlinkt habe?

Mit mit WindowsFormsApplicationBase brauchst du das ganze geraffel nicht.

Hier noch einmal wie es einfacher geht
using-microsoft-visualbasic-applicationservices-to-manage-an-applications-singl