سؤال

وكيف يمكنني برمجيا (في C #) تحديد، إذا ANOTHER تطبيق الأجانب (الأصلي، جافا، .NET أو أيا كان ...) وتطالب حاليا إدخال المستخدم؟ يمكن القيام بذلك بشكل كامل في التعليمات البرمجية المدارة؟

وماذا أنا أبحث عن هو تنفيذ ما يلي:

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

حسب تطالب إدخال المستخدم أعنيه عندما يطلب أحد تطبيقات المستخدم إدخال بعض البيانات أو إنهاء رسالة خطأ (الحوارات مشروط)، وغير قادرة على أداء مهامها العادية بعد الآن. وليس المقصود تطبيق الرسم الذي ينتظر المستخدم لرسم شيء هنا.

وPS: بعد التعديلات لتعكس التعليقات في أسفل وجعل الاهتمام أكثر وضوحا، وبعض التعليقات والردود قد لا تكون 100٪ متسقة مع هذه المسألة. تأخذ ذلك في الاعتبار عند تقييم الإجابات والملاحظات.

هل كانت مفيدة؟

المحلول

وانها في مستحيلة عام. خذ على سبيل المثال نوع شائع من التطبيق، معالج النصوص. في الوقت الحاضر الذي سيقوم بتشغيل spellchecks في الخلفية، بشكل دوري لصناعة السيارات في ينقذ المستند، إلى آخره. بعد من وجهة نظر المستخدمين انها انتظار إدخال كل وقت.

وحالة أخرى شائعة سيكون المشاهد عرض الشرائح. في أي لحظة في الوقت المناسب يمكن أن تضغط على مفتاح لدفع شريحة. بعد أن المستخدم العادي الخاص بك لا يرى ذلك بأنه "انتظار إدخال".

لتلخيص: "انتظار إدخال" دولة الذاتية، وبالتالي لا يمكن تحديده برمجيا

نصائح أخرى

وكيف تحب هذا؟

وعملت من الحل الذي يبدو للعمل، يرجى إعلامي في حالة وجود مشاكل مع هذا الرمز لذلك أنا أيضا الحصول على فائدة من التحسينات. وهو يعمل لبرنامج Excel بقدر ما أنا اختبارها. القضية الوحيدة لم يعجبني هو أن اضطررت إلى استخدام المكالمات غير المدارة. كما أنه يتعامل مع القضية عندما يستند تطبيق على الحوار مثل لMFC مشتقة من 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;
        }
    }
}

إذا كنت أفهم جيدا، قد محاولة تعداد المواضيع العملية وتحقق دولهم. إدارة مهام Windows يفعل شيئا من هذا القبيل. ولكن هذا سيتطلب دالات Win32 - Thread32First وThread32Next من بين أمور أخرى - ولكن يمكنك تحقيق ذلك من خلال أبسط استخدام P / استدعاء في C #:

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

و(توقيع الدقيق قد تختلف).

وتحرير: طيب، هناك وظائف المناظرة في المكتبة. NET

وإذا كان ذلك ممكنا، إعادة كتابة تعليمات برمجية أخرى ليكون معالج إدخال المتزامنة (على غرار خوارزمية لخادم الويب المتزامن):

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

وبطبيعة الحال، يمكن أن لا يزال لديك وظيفة الخاص بك:

static Boolean IsWaitingForUserInput(String processName) {
    return true;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top