문제

다른 외부 응용 프로그램(네이티브, Java, .NET 등...)이 현재 사용자 입력을 요구하는지 프로그래밍 방식으로(C#에서) 어떻게 확인할 수 있습니까?관리 코드에서 이 작업을 완전히 수행할 수 있습니까?

내가 찾고 있는 것은 다음의 구현입니다.

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

사용자 입력을 요구한다는 것은 응용 프로그램이 사용자에게 일부 데이터를 입력하거나 오류 메시지(모달 대화 상자)를 종료하도록 요청하고 더 이상 정상적인 작업을 수행할 수 없는 경우를 의미합니다.사용자가 무언가를 그릴 때까지 기다리는 그리기 애플리케이션은 여기서 의미하지 않습니다.

추신:하단의 의견을 반영하고 우려 사항을 보다 명확하게 편집한 후 일부 의견과 답변이 질문과 100% 일치하지 않을 수 있습니다.답변과 의견을 평가할 때 이 점을 고려하십시오.

도움이 되었습니까?

해결책

일반적으로 불가능합니다. 예를 들어 일반적인 종류의 응용 프로그램, 워드 프로세서를 사용하십시오. 요즘 백그라운드에서 맞춤법 검사를 실행하는 것은 주기적으로 귀하의 문서 등을 자동으로 제공합니다. 그러나 사용자의 관점에서 항상 입력을 기다리고 있습니다.

또 다른 일반적인 경우는 슬라이드 쇼 뷰어입니다. 언제라도 키를 눌러 슬라이드를 전진시킬 수 있습니다. 그러나 일반적인 사용자는 이것을 "입력 대기"로 보지 않습니다.

요약하면 : "입력 대기"는 주관적인 상태이므로 프로그래밍 방식으로 결정할 수 없습니다.

다른 팁

당신은 이것을 어떻습니까?

효과가있는 것처럼 보이는 솔루션을 작성했습니다.이 코드에 문제가 발생하면 나에게 알려 주므로 개선의 혜택도 얻습니다. 내가 테스트 한 한 Excel에서 작동합니다. 내가 싫어하는 유일한 문제는 관리되지 않는 전화를 사용해야한다는 것입니다. 또한 응용 프로그램이 CDIalog에서 파생 된 MFC와 같은 대화 상자를 기반으로하는 경우를 처리합니다.

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 Task Manager는 비슷한 일을합니다. 그러나 여기에는 Win32 기능 -S.Sled32First 및 Thread32Next가 필요하지만 C#에서 P/Invoke를 가장 간단하게 사용하여이를 달성 할 수 있습니다.

    [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