Laden...

externes Programm im Fenster der eigenen Anwendung ausführen

Erstellt von icolor vor 13 Jahren Letzter Beitrag vor 13 Jahren 16.004 Views
Thema geschlossen
I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren
externes Programm im Fenster der eigenen Anwendung ausführen

Mon,

ich habe die Anforderung erhalten, das ich aus einem C# Programm heraus externe Programme aufrufen soll. Allerdings sollen diese nicht wie "normal" auf der Windows-Oberfläche laufen, sondern in einem C# Fenster.
Hat jemand von Euch schon mal was mit einem solchen Problem zu tuen gehabt und kann mir Anhaltspunkte nennen?

Danke

3.511 Beiträge seit 2005
vor 13 Jahren

Hallo,

ja sowas würde gehen, aber es ist total unsauber, weil man nie weiß wie sich die Programme verhalten, wenn diese einen anderen Parent als erwartet erhalten.

Das Fenster innerhalb von c# muss dazu ein MdiContainer sein. Das Fremdfenster musst du dann per SetParent umbiegen. Aber wie gesagt, schön ist was anderes.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren

Okay,

ich habe nun also ein neues Fenster und hole mir dort aus der user32.dll das SetParent. So weit so gut.
Wie geht es jetzt weiter? Ich erstelle derzeit einen Process und übergebe das zu startende Programm.
Und da häng ich jetzt .... Hast Du noch etwas Hilfe für mich?

[DllImport("user32.dll", SetLastError = true)] 
        static extern IntPtr SetParent(IntPtr child, IntPtr newParent);

        public ProgrammStarter()
        {
            InitializeComponent();
        }

        private void ProgrammStarter_Load(object sender, EventArgs e)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = ProgToStart;
            proc.StartInfo.UseShellExecute = true;

            //proc.Start();
        }

Muss ich das Programm zunächst jetzt starten, mir dann die Process ID holen und das dann wieder auf das C# Fenster verbiegen?

Gelöschter Account
vor 13 Jahren

Nein. Du musst dir das Mainwindow des Prozesses Holen, nachdem es gestartet ist und dann musst du mit SetParent sagen, das das Fremde Fenster das Childfenster deines Fensters ist. Das geht alles über den Windowhandle (intptr)

I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren

Super, danke.
Das läuft und ich habe die Programme jetzt im Fenster.

Bleibt nur noch eine Frage:
Wie kann ich das auszuführende Programm im Fenster korrekt positionieren?

Ich mach das derzeit so, um das Programm zunächst nicht anzuzeigen:

[DllImport("user32.dll", SetLastError = true)] 
        static extern IntPtr SetParent(IntPtr child, IntPtr newParent);

        Process proc = new Process();

        public ProgrammStarter()
        {
            InitializeComponent();
        }

        private void ProgrammStarter_Load(object sender, EventArgs e)
        {
            proc.StartInfo.FileName = Sidebar.ProgToStart;
            proc.StartInfo.UseShellExecute = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            proc.Start();
        }

        protected override void OnShown(EventArgs e)
        {
            System.Threading.Thread.Sleep(1000);
            IntPtr processWindowHandle = proc.MainWindowHandle;
            SetParent(processWindowHandle, this.Handle);

            base.OnShown(e);
        }

Das Program wird also Hidden gestartet und ist somit auch im Fenster nciht mehr sichtbar 😦

3.511 Beiträge seit 2005
vor 13 Jahren

Über ShowWindow

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren

Naja, damit wird das Fenster wieder sichtbar. Aber leider nciht maximiert.
Ich möchte dies aber maximiert anzeigen!

3.511 Beiträge seit 2005
vor 13 Jahren

Hast du du ShowWIndow auch mit SW_SHOWMAXIMIZED aufgerufen?

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren

Sorry, mein Fehler.
Jetzt geht es. Ich poste nachher mal den Code, wenn ich fertig bin.
Danke für die Hilfe.

I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren

Ich habe nun nur noch das Problem, das nicht jedes Programm im Fenster dargstellt wird. Ist anscheinend abhängig von der Ladezeit des Programms.

Hat noch jemand eine kurze Idee, wie man das umgehen kann?

1.820 Beiträge seit 2005
vor 13 Jahren

Hallo!

Es gibt in der Process-Klasse die Methode WaitForInputIdle, die könnte dein Problem lösen.

Nobody is perfect. I'm sad, i'm not nobody 🙁

I
icolor Themenstarter:in
115 Beiträge seit 2008
vor 13 Jahren

Ganz hervorragend, danke Tom.

1.820 Beiträge seit 2005
vor 13 Jahren

Hallo!

Reiner Egoismus: Binn gespannt auf die Lösung.

Nobody is perfect. I'm sad, i'm not nobody 🙁

C
37 Beiträge seit 2009
vor 13 Jahren

Da der Code nicht mehr gepostet wurde, stellt sich für mich noch die Frage wie der Prozess angezeigt werden kann.
Soviel ich verstanden habe (MSDN) muss ich mit ShowWindow die Form aufrufen. Leider ist dies aber nicht verfügbar (steckt das nicht in der user32 ?!).

Anbei mein Code zum Aufrufen des Prozesses:

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr child, IntPtr newParent);

        Process proc = new Process();

        private void Form1_Load(object sender, EventArgs e)
        {
            proc.StartInfo.FileName = FILENAME;
            proc.StartInfo.UseShellExecute = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            proc.Start();
            proc.WaitForInputIdle();

            IntPtr processWindowHandle = proc.MainWindowHandle;
            SetParent(processWindowHandle, this.Handle);
            
            ShowWindow(SW_SHOWMAXIMIZED, 3); //FEHLER
        }

Danke schon mal 😃

Gruß
cyn

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo cyntonix,

das DllImport für ShowWindow fehlt ja auch.

In welcher DLL sich die Funktion befindet, steht in der Win32-Doku.

herbivore

Thema geschlossen