如何检测Winforms应用程序已闲置一段时间

检测C#Winforms应用程序是否已空闲一段时间的最佳方法是什么?

如果用户决定ALT + TAB并使用Microsoft Word或其他任何工作30分钟,让我们的应用程序未使用,我希望我们的应用程序自行终止。

这是类似问题的可接受答案: 检查应用程序是否在一段时间内处于空闲状态并将其锁定

但是,答案与Windows闲置一段时间有关, 而不是特定的应用程序。 我希望我们的应用程序终止,如果它没有被用于说,30分钟。

我看着这个:

http://www.codeproject.com/Articles/13756/Detecting-Application-Idleness

但是我在评论中读到这对multithreading应用程序不起作用,我们的应用程序就是其中之一。 我们的应用程序有一个主窗体,它产生模态和无模式窗体,使用Async Await来填充网格等。

然后我查看了SetWindowsHookEx,不确定这是否有用。

当然有人有一个解决方案(希望与.NET 4.5兼容):)

TIA

有很多方法可以做到这一点,答案在某种程度上取决于你需要做什么。 您清楚明确地了解自己的需求。 以下是我开发的可能符合您要求的内容。 它正在做的是使用Application.Idle来确定应用程序何时完成处理消息,然后它设置一个计时器并过滤(监听)应用程序的所有消息,如果收到相关消息(如鼠标或键盘),那么它重置计时器。 它忽略鼠标移动,因为可以在不使用应用程序的情况下将鼠标移动到应用程序上。 自从我写这篇文章已经有一段时间了,所以我不确定细节,但如果有必要,我可以弄清楚。 请注意,这是一个控制台程序,可以使示例更容易尝试,但代码适用于表单应用程序。

using System; using System.Security.Permissions; using System.Windows.Forms; namespace _121414 { static class Program { public static Timer IdleTimer = new Timer(); const int MinuteMicroseconds = 60000; static Form1 f = null; ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); LeaveIdleMessageFilter limf = new LeaveIdleMessageFilter(); Application.AddMessageFilter(limf); Application.Idle += new EventHandler(Application_Idle); IdleTimer.Interval = MinuteMicroseconds; // One minute; change as needed IdleTimer.Tick += TimeDone; IdleTimer.Start(); f = new Form1(); Application.Run(f); Application.Idle -= new EventHandler(Application_Idle); } static private void Application_Idle(Object sender, EventArgs e) { if (!IdleTimer.Enabled) // not yet idling? IdleTimer.Start(); } static private void TimeDone(object sender, EventArgs e) { IdleTimer.Stop(); // not really necessary MessageBox.Show("Auto logoff"); f.Close(); } } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] public class LeaveIdleMessageFilter : IMessageFilter { const int WM_NCLBUTTONDOWN = 0x00A1; const int WM_NCLBUTTONUP = 0x00A2; const int WM_NCRBUTTONDOWN = 0x00A4; const int WM_NCRBUTTONUP = 0x00A5; const int WM_NCMBUTTONDOWN = 0x00A7; const int WM_NCMBUTTONUP = 0x00A8; const int WM_NCXBUTTONDOWN = 0x00AB; const int WM_NCXBUTTONUP = 0x00AC; const int WM_KEYDOWN = 0x0100; const int WM_KEYUP = 0x0101; const int WM_MOUSEMOVE = 0x0200; const int WM_LBUTTONDOWN = 0x0201; const int WM_LBUTTONUP = 0x0202; const int WM_RBUTTONDOWN = 0x0204; const int WM_RBUTTONUP = 0x0205; const int WM_MBUTTONDOWN = 0x0207; const int WM_MBUTTONUP = 0x0208; const int WM_XBUTTONDOWN = 0x020B; const int WM_XBUTTONUP = 0x020C; // The Messages array must be sorted due to use of Array.BinarySearch static int[] Messages = new int[] {WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCMBUTTONDOWN, WM_NCMBUTTONUP, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP}; public bool PreFilterMessage(ref Message m) { if (m.Msg == WM_MOUSEMOVE) // mouse move is high volume return false; if (!Program.IdleTimer.Enabled) // idling? return false; // No if (Array.BinarySearch(Messages, m.Msg) >= 0) Program.IdleTimer.Stop(); return false; } } } 

您需要确定“空闲”的含义。 我假设应用程序在所需时间内没有收到鼠标或键输入。

您可以添加一个消息filter,以查看所有应用程序范围的Windows消息。 请参见Application.AddMessageFilter 。 检查按键和鼠标按下的消息代码,并记录上次发生的消息代码,但返回false,以便运行时正常处理所有消息。 可能的代码是:

 WM_LBUTTONDOWN = 513 RBUTTONDOWN = 516 WM_KEYDOWN = 256 

然后在其他地方的单独计时器中检查最后一个事件是否超过30分钟。

“终止”应用程序也存在潜在问题。 如果应用程序打开了模态窗体,听起来好像它可能不是特别安全的状态突然杀死。