99
1010namespace EventHook
1111{
12+ /// <summary>
13+ /// An enum for the type of application event
14+ /// </summary>
1215 public enum ApplicationEvents
1316 {
1417 Launched ,
1518 Closed ,
1619 Activated
1720
1821 }
22+
23+ /// <summary>
24+ /// An object that holds information on application event
25+ /// </summary>
1926 public class WindowData
2027 {
2128 public IntPtr HWnd ;
@@ -26,12 +33,19 @@ public class WindowData
2633 public string AppTitle { get ; set ; }
2734 }
2835
36+ /// <summary>
37+ /// An event argument object send to user
38+ /// </summary>
2939 public class ApplicationEventArgs : EventArgs
3040 {
3141 public WindowData ApplicationData { get ; set ; }
3242 public ApplicationEvents Event { get ; set ; }
3343 }
3444
45+ /// <summary>
46+ /// A wrapper around shell hook to hook application window change events
47+ /// Uses a producer-consumer pattern to improve performance and to avoid operating system forcing unhook on delayed user callbacks
48+ /// </summary>
3549 public class ApplicationWatcher
3650 {
3751 /*Application history*/
@@ -45,6 +59,9 @@ public class ApplicationWatcher
4559
4660 public static event EventHandler < ApplicationEventArgs > OnApplicationWindowChange ;
4761
62+ /// <summary>
63+ /// Start to watch
64+ /// </summary>
4865 public static void Start ( )
4966 {
5067 if ( ! _IsRunning )
@@ -54,15 +71,16 @@ public static void Start()
5471 _prevTimeApp = DateTime . Now ;
5572
5673 appQueue = new AsyncCollection < object > ( ) ;
57-
5874
75+ //This needs to run on UI thread context
76+ //So use task factory with the shared UI message pump thread
5977 Task . Factory . StartNew ( ( ) => { } ) . ContinueWith ( x =>
60- {
61- WindowHook . WindowCreated += new GeneralShellHookEventHandler ( WindowCreated ) ;
62- WindowHook . WindowDestroyed += new GeneralShellHookEventHandler ( WindowDestroyed ) ;
63- WindowHook . WindowActivated += new GeneralShellHookEventHandler ( WindowActivated ) ;
78+ {
79+ WindowHook . WindowCreated += new GeneralShellHookEventHandler ( WindowCreated ) ;
80+ WindowHook . WindowDestroyed += new GeneralShellHookEventHandler ( WindowDestroyed ) ;
81+ WindowHook . WindowActivated += new GeneralShellHookEventHandler ( WindowActivated ) ;
6482
65- } , SharedMessagePump . GetTaskScheduler ( ) ) ;
83+ } , SharedMessagePump . GetTaskScheduler ( ) ) ;
6684
6785 _lastEventWasLaunched = false ;
6886 _lastHwndLaunched = IntPtr . Zero ;
@@ -72,6 +90,10 @@ public static void Start()
7290 }
7391
7492 }
93+
94+ /// <summary>
95+ /// Quit watching
96+ /// </summary>
7597 public static void Stop ( )
7698 {
7799 if ( _IsRunning )
@@ -86,19 +108,44 @@ public static void Stop()
86108 }
87109
88110 }
111+
112+ /// <summary>
113+ /// A windows was created on desktop
114+ /// </summary>
115+ /// <param name="shellObject"></param>
116+ /// <param name="hWnd"></param>
89117 private static void WindowCreated ( ShellHook shellObject , IntPtr hWnd )
90118 {
91119 appQueue . Add ( new WindowData ( ) { HWnd = hWnd , EventType = 0 } ) ;
92120 }
121+
122+ /// <summary>
123+ /// An existing desktop window was destroyed
124+ /// </summary>
125+ /// <param name="shellObject"></param>
126+ /// <param name="hWnd"></param>
93127 private static void WindowDestroyed ( ShellHook shellObject , IntPtr hWnd )
94128 {
95129 appQueue . Add ( new WindowData ( ) { HWnd = hWnd , EventType = 2 } ) ;
96130 }
131+
132+ /// <summary>
133+ /// A windows was brought to foreground
134+ /// </summary>
135+ /// <param name="shellObject"></param>
136+ /// <param name="hWnd"></param>
97137 private static void WindowActivated ( ShellHook shellObject , IntPtr hWnd )
98138 {
99139 appQueue . Add ( new WindowData ( ) { HWnd = hWnd , EventType = 1 } ) ;
100140 }
101- // This is the method to run when the timer is raised.
141+
142+ /// <summary>
143+ /// This is used to avoid blocking low level hooks
144+ /// Otherwise if user takes long time to return the message
145+ /// OS will unsubscribe the hook
146+ /// Producer-consumer
147+ /// </summary>
148+ /// <returns></returns>
102149 private static async Task AppConsumer ( )
103150 {
104151 while ( _IsRunning )
@@ -123,7 +170,16 @@ private static async Task AppConsumer()
123170
124171 }
125172 }
173+
174+ /// <summary>
175+ /// A handle to keep track of last window launched
176+ /// </summary>
126177 private static IntPtr _lastHwndLaunched ;
178+
179+ /// <summary>
180+ /// A window got created
181+ /// </summary>
182+ /// <param name="wnd"></param>
127183 private static void WindowCreated ( WindowData wnd )
128184 {
129185
@@ -135,6 +191,11 @@ private static void WindowCreated(WindowData wnd)
135191
136192 }
137193
194+ /// <summary>
195+ /// invoke user call back
196+ /// </summary>
197+ /// <param name="wnd"></param>
198+ /// <param name="appEvent"></param>
138199 private static void ApplicationStatus ( WindowData wnd , ApplicationEvents appEvent )
139200 {
140201 var timeStamp = DateTime . Now ;
@@ -143,13 +204,13 @@ private static void ApplicationStatus(WindowData wnd, ApplicationEvents appEvent
143204 wnd . AppPath = appEvent == ApplicationEvents . Closed ? wnd . AppPath : WindowHelper . GetAppPath ( wnd . HWnd ) ;
144205 wnd . AppName = appEvent == ApplicationEvents . Closed ? wnd . AppName : WindowHelper . GetAppDescription ( wnd . AppPath ) ;
145206
146- EventHandler < ApplicationEventArgs > handler = OnApplicationWindowChange ;
147- if ( handler != null )
148- {
149- handler ( null , new ApplicationEventArgs ( ) { ApplicationData = wnd , Event = appEvent } ) ;
150- }
207+ OnApplicationWindowChange ? . Invoke ( null , new ApplicationEventArgs ( ) { ApplicationData = wnd , Event = appEvent } ) ;
151208 }
152209
210+ /// <summary>
211+ /// Remove handle from active window collection
212+ /// </summary>
213+ /// <param name="wnd"></param>
153214 private static void WindowDestroyed ( WindowData wnd )
154215 {
155216
@@ -160,6 +221,10 @@ private static void WindowDestroyed(WindowData wnd)
160221 }
161222 _lastEventWasLaunched = false ;
162223 }
224+
225+ /// <summary>
226+ /// Add window handle to active windows collection
227+ /// </summary>
163228 private static bool _lastEventWasLaunched ;
164229 private static void WindowActivated ( WindowData wnd )
165230 {
0 commit comments