Laden...

Wie bekomme ich den MainWindowHandle wenn showInTaskbar = false gesetzt ist?

Erstellt von Pico1184 vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.497 Views
Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 3 Jahren
Wie bekomme ich den MainWindowHandle wenn showInTaskbar = false gesetzt ist?

Hallo,

ich muss kurz etwas ausholen damit man verstehen kann um was es geht:

.net framework 4.6.1

Ich bin aktuell an einer Industrie Anlage / Maschine und habe dort einen Windows 10 Rechner mit zwei Monitoren über DVI, auf welchem eine spezielle WPF Anwendung läuft.

Die WPF Anwendung ersetzt die Standard Windows Shell, da es den Bedienern der Maschine unter keinen Umständen ermöglicht werden soll auf die Betriebssystem Ebene zu gelangen.

Soweit so gut, das passt auch alles. Nun ist es allerdings so, dass ich aus dieser Shell eine weitere WPF Anwendung starten muss (diese ist maximiert, Vollbild und ShowInTaskbar = false). Auch dies funktioniert einwandfrei über die bekannte “Process” Klasse).

Allerdings muss ich diese Anwendung automatisch auf dem zweiten Monitor öffnen.
Dazu wollte ich die “setwindowspos” Funktion aus der WinApi nutzen.

Diese erwartet allerdings ein handle auf das betroffene Fenster. Nun genau dies ist mein Problem. Ich bekomme über “Process.MainWindowHandle” immer ein Null Handle. Ich gehe davon aus, dass dies damit zu tun hat, dass die Anwendung außerhalb der taskbar (showintaskbar = false) läuft.

Habe auch schon “FindWindow” etc aus der WinApi probiert aber leider keine Chance.
Hat irgendjemand eine Idee wie ich an dieses Window Handle ran komme damit ich das Fenster auf den zweiten Monitor verschieben kann?

Viele Grüße

Pico

16.828 Beiträge seit 2008
vor 3 Jahren

Das Einschränken des Betriebssystem ist ja eine übliche Handhabe im Maschinenbau und in der Industrie; aber warum verwendet ihr nicht den Kiosk Mode - wie eben auch weit verbreitet?
Der ist ja genau für solche Dinge gedacht - und ihr könnt alle System-Apps wie gewohnt nutzen oder alternativ die Berechtigungen durch den App Locker setzen.

Ich bekomme über “Process.MainWindowHandle” immer ein Null Handle. Ist das immer noch das gleiche Process Objekt wie beim Starten?
Dann musst Du die Refresh() Methode ausführen.

Der letzte Workaround ist, dass Du Dir beim Starten die Process Id holst und dann das Fenster anhand der Process Id ermittelst.

4.938 Beiträge seit 2008
vor 3 Jahren

Mit der Taskbar hat das m.E. nichts zu tun. Wartest du denn auf das Erscheinen des Hauptfensters nach Process.Start mittels WaitForInputIdle?

Auch ich würde den Kiosk-Modus dafür bevorzugen.

P
57 Beiträge seit 2017
vor 3 Jahren

Ist die primäre Anwendung von euch oder vom Hersteller?

Das wäre nicht schlecht zu wissen.

.....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....

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 3 Jahren

Die Anwendung ist von uns. Das mit dem Kiosk Modus könnte ich mal checken, allerdings weiß ich nicht ob dies mein aktuelles Problem beheben würde (starten eines neuen Prozesses auf dem zweiten Monitor).

Ich habe verschiedenes probiert. Hier mal ein Auszug:


                var path = Assembly.GetExecutingAssembly().Location;

                var secondHmiProcess = new Process
                {
                    EnableRaisingEvents = true,
                    StartInfo =
                    {
                       FileName = path, 
                       Arguments = "exec=true", 
                       UseShellExecute = false
                    }
                };
                secondHmiProcess.Start();
                secondHmiProcess.WaitForInputIdle(-1);

             
                SetWindowPos(secondHmiProcess.MainWindowHandle, HWND_TOPMOST, (int)secondMonitor.Left, (int)secondMonitor.Top, (int)secondMonitor.Width, (int)secondMonitor.Height, 0);

oder


                var path = Assembly.GetExecutingAssembly().Location;

                var secondHmiProcess = new Process
                {
                    EnableRaisingEvents = true,
                    StartInfo =
                    {
                       FileName = path, 
                       Arguments = "exec=true", 
                       UseShellExecute = false
                    }
                };
                secondHmiProcess.Start();
              
                for (var i = 0; i < 50; i++)
                {
                  Thread.Sleep(100);
                  secondHmiProcess.Refresh();

                  if(secondHmiProcess.MainWindowHandle != IntPtr.Zero)
                      break;
                }

             
                SetWindowPos(secondHmiProcess.MainWindowHandle, HWND_TOPMOST, (int)secondMonitor.Left, (int)secondMonitor.Top, (int)secondMonitor.Width, (int)secondMonitor.Height, 0);


Habe auch probiert an das Handle über die ProzessId bzw. den Namen zu kommen, allerdings ist es immer Null.

Diese Anwendung soll sich auf dem zweiten Monitor nochmal selbst (als neuer Prozess) starten und hat folgende Parameter:

ResizeMode = NoRezise
ShowInTaskbar = False
WindowState = Maximized
WindowStartupLocation = CenterScreen
WindowStyle = None

Grüße

P
57 Beiträge seit 2017
vor 3 Jahren

Sieht mir gerade eher danach aus, als würdest du die aktuelle Anwendung starten.....


var path = Assembly.GetExecutingAssembly().Location;

@Abt: Ist das gewollt, dass die CodeTags nur mit dem BeginnigTag erstellt werden?

.....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....

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 3 Jahren

so siehts aus, ich möchte die selbe Anwendung nochmal starten und auf den zweiten Monitor schieben, so dass auf beiden Monitoren die gleiche Anwendung (allerdings in unterschiedlichen Instanzen) läuft.

P
57 Beiträge seit 2017
vor 3 Jahren

.....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....

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 3 Jahren

Danke dir, allerdings möchte ich keine Referenz zu Windows Forms verwenden.

P
57 Beiträge seit 2017
vor 3 Jahren

Dann schau mal hier: WPF-MVVM Window auf zweitem Monitor öffnen

Ist hier aus dem Forum.

Letzter Post.

Entweder so oder du machst es so wie Abt vorgeschlagen hat: PID vom laufenden Prozess holen und dann damit arbeiten.

.....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....

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 3 Jahren

Sorry auch dieser Lösungsweg verweist auf Windows Forms und weiter oben habe ich geschrieben, das es leider auch nicht mit der Process Id funktioniert, da auch hier ebenfalls ein Null handle geliefert wird.

16.828 Beiträge seit 2008
vor 3 Jahren

allerdings weiß ich nicht ob dies mein aktuelles Problem beheben würde (starten eines neuen Prozesses auf dem zweiten Monitor).

Das härtet das gesamte System.

das es leider auch nicht mit der Process Id funktioniert, da auch hier ebenfalls ein Null handle geliefert wird.

Das wird so wie es programmiert ist weniger am Handle liegen, sondern an der Umsetzung.
Das Handle wird einfach viel später zur Verfügung stehen als Du abfrägst, zB. weil die Applikation langsam startet.

Davon abgesehen basiert MainWindowHandle nicht auf einem absoluten Wert sondern im Endeffekt wird geraten, welches Handle Main ist - und das klappt nicht immer.
Willst Du ein spezifisches Window, dann musst Du mit EnumWindows arbeiten.

@Abt: Ist das gewollt, dass die CodeTags nur mit dem BeginnigTag erstellt werden?){gray} In der aktuellen Fassung bei phpBB wird beim ersten Klick das Beginning-Tag erstellt und beim zweiten Click das Close.
In einer zukünftigen Fassung des Forums wird ein Klick beides auf einmal erzeugen.

4.938 Beiträge seit 2008
vor 3 Jahren

Für WPF-Anwendungen s. Application.MainWindow.

PS: Warum übergibst du nicht einfach die Screen-Nummer bzw. das absolute Rechteck als weitere Parameter (dann brauchst du nicht nachträglich den neuen Process von außen steuern).

Pico1184 Themenstarter:in
223 Beiträge seit 2009
vor 3 Jahren

Habe es jetzt anders gelöst. Ich starte einfach ein zweites Window und öffne dieses dann auf dem zweiten Monitor. Danke euch dennoch für die Hilfe!