我如何编程(C#中)确定,如果另一个外国申请(本机,JAVA,.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 - 但你可以通过在C#中最简单的使用的P / Invoke的实现这一点:
[DllImport("Executor.dll")]
public static extern bool Thread32First(IntPtr handle, IntPtr threadEntry32);
(精确签名可能不同)。
编辑:好的,也有在.NET库相应的功能。
如果可能,改写其他代码是一个并行输入处理器(类似算法并发web服务器):
Wait for input
Fork process
Parent: Repeat
Child: (Worker) handle input
当然,你仍然可以有你的功能:
static Boolean IsWaitingForUserInput(String processName) {
return true;
}