Frage

Wie kann ich programmatisch (in C #) bestimmen, wenn ein anderen Fremd Anwendung (native, Java, .NET oder was auch immer ...) zur Zeit verlangt Benutzereingaben? Kann diese vollständig in verwaltetem Code zu tun?

Was ich suche ist die Implementierung:

static Boolean IsWaitingForUserInput(String processName)
{
    ???
}

Mit dem anspruchsvollen Benutzereingabe ich meine, wenn eine Anwendung die Benutzer auffordert, mehr einige Daten oder beenden eine Fehlermeldung (Modal Dialoge) und ist nicht in der Lage zu führen ihre normalen Aufgaben einzugeben. Eine Zeichnung Anwendung, die für den Benutzer wartet etwas zu zeichnen ist hier nicht gemeint.

PS: Nach der Bearbeitung der Kommentare unten zu reflektieren und die Sorge klarer machen, einig Kommentare und Antworten können nicht zu 100% im Einklang mit der Frage sein. Berücksichtigen Sie dies, wenn die Antworten und Bemerkungen zu bewerten.

War es hilfreich?

Lösung

Es ist im Allgemeinen nicht möglich. Nehmen wir zum Beispiel eine gemeinsame Art von Anwendung, ein Textverarbeitungsprogramm. Heute, die Rechtschreibprüfung im Hintergrund ausgeführt wird, sie in regelmäßigen Abständen automatisch speichert Ihr Dokument, und so weiter. Doch von einem Benutzer Perspektive für die Eingabe es wartet die ganze Zeit.

Ein weiterer häufiger Fall wäre eine Slideshow-Viewer sein. Zu jedem Zeitpunkt können Sie eine Taste drücken, um eine Folie zu wechseln. Doch die typische Benutzer nicht sieht dies als „für die Eingabe wartet“.

Um es zusammenzufassen:. „Für die Eingabe wartet“ ist ein subjektiver Zustand und kann daher nicht durch Software bestimmt werden

Andere Tipps

Wie gefällt Ihnen das?

arbeitete ich eine Lösung aus, die, bitte informieren Sie mich bei Problemen mit diesem Code, damit ich auch gewinnen Nutzen von Verbesserungen zu arbeiten scheint. Es funktioniert für Excel, soweit ich getestet. Die einzige Frage, die ich nicht mag, ist, dass ich nicht verwalteten Anrufe verwenden musste. Es ist auch für den Fall, wenn eine Anwendung auf einem Dialog wie für MFC basiert, abgeleitet von CDialog.

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

namespace Util
{
    public class ModalChecker
    {
        public static Boolean IsWaitingForUserInput(String processName)
        {
            Process[] processes = Process.GetProcessesByName(processName);
            if (processes.Length == 0)
                throw new Exception("No process found matching the search criteria");
            if (processes.Length > 1)
                throw new Exception("More than one process found matching the search criteria");
            // for thread safety
            ModalChecker checker = new ModalChecker(processes[0]);
            return checker.WaitingForUserInput;
        }

        #region Native Windows Stuff
        private const int WS_EX_DLGMODALFRAME = 0x00000001;
        private const int GWL_EXSTYLE = (-20);
        private delegate int EnumWindowsProc(IntPtr hWnd, int lParam);
        [DllImport("user32")]
        private extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);
        [DllImport("user32", CharSet = CharSet.Auto)]
        private extern static uint GetWindowLong(IntPtr hWnd, int nIndex);
        [DllImport("user32")]
        private extern static uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
        #endregion

        // The process we want the info from
        private Process _process;
        private Boolean _waiting;

        private ModalChecker(Process process)
        {
            _process = process;
            _waiting = false; //default
        }

        private Boolean WaitingForUserInput
        {
            get
            {
                EnumWindows(new EnumWindowsProc(this.WindowEnum), 0);
                return _waiting;
            }
        }

        private int WindowEnum(IntPtr hWnd, int lParam)
        {
            if (hWnd == _process.MainWindowHandle)
                return 1;
            IntPtr processId;
            GetWindowThreadProcessId(hWnd, out processId);
            if (processId.ToInt32() != _process.Id)
                return 1;
            uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
            if ((style & WS_EX_DLGMODALFRAME) != 0)
            {
                _waiting = true;
                return 0; // stop searching further
            }
            return 1;
        }
    }
}

Wenn ich dich gut verstehen, können Sie versuchen, den Prozess des Threads aufzuzählen und ihre Zustände zu überprüfen. Windows Task-Manager macht etwas Ähnliches. Dies wird jedoch Win32-Funktionen benötigen - Thread32First und Thread32Next unter anderem - aber Sie können dies durch die einfachste Verwendung von P / Invoke in C # erreichen:

    [DllImport("Executor.dll")]
    public static extern bool Thread32First(IntPtr handle, IntPtr threadEntry32);

(Precise Signatur kann abweichen).

EDIT:. Ok, es sind entsprechende Funktionen in der .NET-Bibliothek

Wenn möglich, schreiben Sie den anderen Code, um einen gleichzeitigen Eingangsprozessor (ähnlich den Algorithmus für einen gleichzeitigen Web-Server) zu sein:

Wait for input
Fork process
  Parent: Repeat
  Child: (Worker) handle input

Natürlich könnten Sie immer noch Ihre Funktion haben:

static Boolean IsWaitingForUserInput(String processName) {
    return true;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top