2010-08-12 11 views
20

Einige unserer nicht-technischen Benutzer haben Probleme, wo ein Dialogfeld MessageBox in unserer Anwendung manchmal hinter dem Hauptformular angezeigt werden kann und die Anwendung keine Eingabe akzeptiert, bis die messagebox (die sie kann nicht sehen) wird entlassen.Dialog MessageBox manchmal hinter dem Hauptformular versteckt

Die Anwendung ist in C# geschrieben und die Meldungsfelder sind Standard zB der Code kann so einfach sein wie MessageBox.Show (Nachricht, Beschriftung) und die Messageboxen können vom Haupt-UI-Thread erstellt werden (dh kein Hintergrund-Thread) . Die Anwendung muss nicht im Vollbildmodus ausgeführt werden, aber 90% unserer Benutzer führen sie im Vollbildmodus aus.

Die meiste Zeit ((vielleicht> 99%) die Message korrekt angezeigt und ich habe es nie geschafft, zu sehen, wie es schief geht, aber ich habe eine Maschine gesehen, wenn es schief gegangen ist.

Eine Sache, die ich Wenn Sie eine Anwendung haben, die ein Dialogfeld anzeigt, sehen Sie normalerweise nur einen Eintrag in der Anwendungsliste.Wenn die Nachrichtenbox ausgeblendet wird, sehen Sie zwei Einträge, einen für den Hauptbildschirm Anwendung und ein weiterer Eintrag für dieses Meldungsfeld

Es ist einfach genug, das Problem zu beheben, sobald Sie wissen, was passiert ist, aber einige unserer nicht technischen Benutzer sind davon verwirrt und schalten sie aus r Computer. (Und diejenigen, die Remotedesktop verwenden, sind noch verwirrter, wenn dies das Problem nicht löst).

Ich glaube nicht, dass es mit dem Betriebssystem verbunden ist, wie ich es in Vista geschehen gesehen habe und es wurde auch in einer Terminal-Sitzung auf einem Windows 2003-Server passiert.

Weiß irgendjemand, warum das passiert und, was noch wichtiger ist, wenn etwas getan werden kann, um es zu vermeiden?

+0

Ich habe das gleiche Problem mit WPF erlebt. Etwas kann die Beziehung zwischen dem Dialog und dem Hauptfenster auslösen, die normalerweise existiert, auch wenn sie nicht spezifiziert ist, um gebrochen zu werden. Die Bereitstellung eines Fensters als erstes Argument hat das Problem behoben. Um es neu zu erstellen, habe ich die Anwendung im VS-Debugger ausgeführt. Der aktive Debugger scheint die Beziehung oft zu unterbrechen. Sie können feststellen, dass das Problem aufgetreten ist, da das Dialogfeld einen eigenen Eintrag in der Taskleiste erhält. – denver

Antwort

18

Einige Überladungen der MessageBox.Show() Methode nehmen einen IWin32Window Parameter als erstes Argument. Wenn Sie Ihr Formular als erstes Argument übergeben, sollte dies verhindert werden.

+0

+1 für die Angabe des übergeordneten Fensters. Das Problem von OP bedeutet höchstwahrscheinlich, dass das Nachrichtenfeld ein Null-Elternteil (d. H. Desktop-Fenster) hat und manchmal dieses Fenster im Hintergrund endet. – casablanca

+0

Gibt es eine Möglichkeit zu bestimmen, was das übergeordnete Element der Nachrichtenbox ist (zur Laufzeit und auf dem Computer eines Kunden)? – sgmoore

+2

http://www.catch22.net/software/winspy kann Ihnen sagen. –

0

Sie sagen "die messageboxes können durch den Haupt-UI-Thread erstellt werden", was bedeutet, dass sie nicht immer vom Haupt-UI-Thread erstellt werden. Ihr Problem klingt wie MessageBox.Show wird gelegentlich von einem anderen Thread aufgerufen.

+0

Nö, was ich meinte war, dass es, obwohl es manchmal mit Meldungsfeldern, die von Hintergrundthread erstellt wurden, stattgefunden hat, auch in Meldungsfeldern vorkommt, die definitiv vom Hauptthread der Benutzeroberfläche erstellt werden. – sgmoore

+0

Machst du etwas funky in deiner Form? Wie PInvoing SetWindowPos oder etwas ähnliches? – MusiGenesis

+0

Nein. Das einzige Übliche ist, dass ShowInTaskbar auf false gesetzt wird, bevor das Hauptformular tatsächlich angezeigt wird, während ein Begrüßungsbildschirm angezeigt wird und das Programm initialisiert wird. ShowInTaskbar wird am Ende des Mainform Load-Ereignisses auf True gesetzt. – sgmoore

1

Ist es immer das gleiche Meldungsfeld (für die gleiche Nachricht?) Kommt das gleiche Formular?

Im Idealfall sollten Sie versuchen, eine Möglichkeit zu finden, das Problem nach Belieben oder zumindest automatisch zu reproduzieren. Dadurch wird das Debuggen einfacher und Sie können sicher sein, dass Ihre zukünftige Änderung den Fehler behoben hat und nicht erst nach ein paar Wochen auf das Feedback Ihrer Benutzer warten muss.

Wenn es immer die gleiche Nachricht und im selben Fenster ist, die sich aus der gleichen Aktion ergeben, und wenn der MessageBox-Aufruf einigermaßen einfach aus Sicht eines Benutzers ausgelöst werden kann und wenn Ihre Benutzeroberfläche relativ standard ist könnte die Benutzeroberfläche mit einem AutoIT Skript automatisieren und es in einer Schleife laufen lassen, bis das Problem auftritt.

Und/oder Sie könnten ein "Debug" -Build Ihrer Anwendungen erstellen, das Sie einigen Benutzern geben könnten (vorzugsweise diejenigen, die am häufigsten auf das Problem zu stoßen scheinen), die den Inhalt eines schreiben würden StackFrame Objekt vor jedem Aufruf einer MessageBox in eine Protokolldatei oder etwas ähnliches (Sie könnten einen Wrapper um die MessageBox erstellen, um dies zu vereinfachen).

Dann, wenn einer Ihrer Benutzer das Problem bekommt, können Sie sich die Protokolldatei ansehen und sehen, wo sie herkommt (Quellcode-Datei, Zeile, Aufruf-Stack usw.). Sie können dies auch mit den Protokollen von anderen Benutzern vergleichen und sehen, ob die MessageBox immer von demselben Ort kommt oder wenn sie variiert. Dies würde Ihnen zeigen, wo die problematische MessageBox von wo aufgerufen wird.

Möglicherweise gibt es einfachere Lösungen (vor allem, wenn Ihre Anwendung viele Assemblys hat) mit einigen. Net-Debugger, die Sie an Ihre Anwendung anschließen würden, wenn das Problem auftritt, um den Aufruf-Stack usw. zu sehen, aber ich tat es nur dies mit nativen Anwendungen (mit OllyDbg) bisher und nicht .Net. Andere sind möglicherweise in der Lage, weiter auf diese Idee zu erweitern ...

+0

Es ist nicht immer die gleiche Nachricht und die Messageboxen können aus verschiedenen Teilen des Programms erstellt werden. Als ich die Nachricht das letzte Mal gesehen habe, wusste ich aus der Nachricht, woher sie kam. Das Problem über versuchen, es zu automatisieren ist, dass ich denke, dass externe Faktoren an Ort und Stelle kommen. Als es zuerst gemeldet wurde, dachte ich, es könnte durch den Benutzer verursacht werden, der die Anwendung minimiert, um an einem anderen Programm zu arbeiten, und das Nachrichtenfeld wird erstellt, während die Anwendung minimiert wird. Aber wenn ich das tue, wenn ich zu meiner Anwendung zurückwechsle, wird das Nachrichtenfeld auch vorne angezeigt. – sgmoore

+0

Wenn Sie die Threading-Hypothese bereits ausgeschlossen haben, denke ich, dass Sie möglicherweise so viele gewöhnliche Verdächtige wie möglich ausschließen müssen. Haben Sie versucht, Ihre Anwendung auf einer fehlerfreien Maschine (oder VM) auszuführen? Nicht sicher, wie praktisch es in Ihrer Umgebung ist, aber, obwohl selten, ist es nicht unmöglich, dass ein Dienstprogramm oder eine andere Software versucht, den Fokus zu einem bestimmten Zeitpunkt zu stehlen oder einige seltsame Dinge mit den Fenstern passieren zu lassen. Außerdem sieht es so aus, als hätten Sie den Bug nie selbst erlebt. –

+0

Wenn Ihre Benutzer interne Mitarbeiter sind und bereit sind, sie anzunehmen, können Sie ihren Bildschirm aufzeichnen, damit Sie sehen können, was passiert ist, wenn sie das nächste Mal beim Auftreten des Problems angerufen werden. Die Tatsache, dass sie beobachtet werden, kann jedoch einen seltsamen Placebo-Effekt in sich auslösen (wenn der Benutzer auf Websites geht, während Ihre Anwendung beispielsweise etwas verarbeitet und nicht mehr weiß, dass Sie die Aufzeichnung ansehen können). –

1

Bestätigen Sie das Problem. Was wir tun, um es zu beheben, ist folgendes: 1. Neue Aufgabe ausführen und das Meldungsfeld anzeigen 2. Im Haupt-UI-Thread, während Task noch läuft - warten Sie in der Schleife, die DoEvents tut. So etwas wie dieses

AKTUALISIERT 2015-12-17. Reproduziert Problem yestarday. In meinem Fall Repo - Minimiere die App, "Warte" Popup tritt auf (in unserem Fall passiert es nach einiger Leerlaufzeit), dann klicke in der Taskleiste auf das Haupt App Icon. Dies "versteckt" das Popup, so dass es nicht möglich ist, es auf den Bildschirm zu bringen. Der folgende Code wurde getestet und löst das Problem. Aber ich verstehe immer noch nicht, was/warum es passiert.

private static DialogResult ShowMessageBox(
     string message, 
     string caption, 
     MessageBoxButtons buttons, 
     MessageBoxIcon icon) 
    { 

     var showMessageBoxTask = new Task<DialogResult>(() => 
     { 
      var form = new Form() {TopMost = true}; 

      var result = MessageBox.Show(
       form, 
       PrepareMessage(message), 
       caption, 
       buttons, 
       icon); 

      form.Dispose(); 

      return result; 
     }); 

     showMessageBoxTask.Start(); 

     while (!showMessageBoxTask.IsCompleted && !showMessageBoxTask.IsFaulted) 
     { 
      Application.DoEvents(); 
     } 

     return showMessageBoxTask.Result; 
    } 
Verwandte Themen