A quick tip for those of us fond of iisreset. Restarting IIS takes quite a while. Sometimes 15-20 seconds, when my w3wp.exe processes are particularly unruly. In many cases, though, a full iisreset is unnecessary. Since IIS 6.0 expanded its process isolation model to include Application Pools, the simplest way is to simply recycle the application pool - takes only a second, and usually does the trick.
We can do this in .NET with very little effort:
using
(DirectoryEntry appPool = new DirectoryEntry(string.Format("IIS://{0}/w3svc/apppools/{1}", host, poolname)))
{
appPool.Invoke("Recycle");
} Or, if we want to use this in automation scripts or post-build events, we can wrap this in a console application (Here, full source code).
Enjoy.
I've been having an argument with a co-worker of mine about the KeyboardHook code I recently published here.
His claim - by exposing a KeyboardHook object and letting users add Filters for specific keystrokes, I am exposing too much of my inner implementation that shouldn't interest the user of my library. Properly abstracted and refactored, the user should treat each KeyboardHook object as a specific keystroke-capture object, not have to deal with two different objects here. Various implementation details like explicitly calling Install() should be implicitly called whenever the event is hooked up to an event handler, rather than being left to the innocent caller.
While my code uses this:
KeyboardHook hook = new KeyboardHook();
hook.AddFilter(Keys.F, true, false, true);
hook.AddFilter(Keys.F6, false, true, false);
hook.KeyPressed +=new KeyboardHookEventHandler(hook_KeyPressed);
hook.Install();
He believes it should be more like this:
KeyboardHook firstHook = KeyboardHook.Create(Keys.F, true, false, true);
KeyboardHook secondHook = KeyboardHook.Create(Keys.F6, false, true, false);
firstHook.KeyPressed +=new KeyboardHookEventHandler(firstHook_KeyPressed);
secondHook.KeyPressed +=new KeyboardHookEventHandler(secondHook_KeyPressed);
My counter-claim is that while this may be more abstract and refactored, it may be taking it a bit too far. A Windows hook is an actual operating system object, not just a logical construct I create in my code, and there can be serious performance implications for defining one of them for each keystroke rather than defining just one generic hook for all strokes. Furthermore, I want the users of my library to be aware of this difference, rather than hiding this information. I want them to be aware of the implications of having a hook installed, and allow them to install and uninstall it selectively.
His counter-counter-claim was that I can implement all my static methods to hide the actual system hook and have all my KeyboardHook objects actually receive their events from that one OS object. I can have a reference counting mechanism set up to allow me to disable individual hooks, and only uninstall the inner hook when all stroke-captures are disabled.
My prompt reply was that this might, indeed, produce rather clean and elegant code. However, it would also involve rewriting most of the existing code for this library for a relatively small and theoretical gain for the library user, and I'll be damned if I go and do that any time soon, and he's welcome to do it himself if he-thinks-he-knows-so-much.
The conversation generally deteriorated from that point onwards.
So, anyone have any comments on the current design or the proposed changes, the benefits and shortcomings of both?
While trying to implement custom shortcut keys in Outlook, I came across an old column by Dino Esposito on implementing custom Windows hooks in .NET. At first I wanted to use it as reference and inspiration only, and only when I finished did I notice I simply rewrote, from scratch, most of the code he offers in his article. The main difference is that he supplies a base, generic WindowsHook class and a derived CBTHook class to handle window opening/closing/etc events, while I implemented my generic parent class and a derived KeyboardHook class for keyboard events. This is implemented as thread-local hooks on the currently running process, rather than expensive global system hooks.
The basic premise is simple - keep all the Win32 P/Invoke code well hid inside the private implementation, and have the WindowsHook class simply raise an event when the hook function is invoked, passing the hook function paraemeters as event args to the HookInvoked event.
However, since the hook parameters are different for each kind of hook, the KeyboardHook class also raises a different event, KeyPressed, that parses the hook parameters and gives more intelligble and specific meaning to the parameters - which key was pressed, as well as the state of the Control, Alt and Shift keys.
Additionally, the KeyboardHook class allows setting filters, so that the event will only be raised for specific keystrokes. This allows us to get only the keystrokes we want (say, our chosen keyboard shortcut keys).
Code such as this sample will raise the KeyPressed event whenever the user presses Ctrl-Shift-F, or Alt-F6:
KeyboardHook hook;
private void Form1_Load(object sender, System.EventArgs e)
{
hook = new KeyboardHook();
hook.AddFilter(Keys.F, true, false, true);
hook.AddFilter(Keys.F6, false, true, false);
hook.KeyPressed +=new KeyboardHookEventHandler(hook_KeyPressed);
hook.Install();
}
KeyboardHook hook;
private void Form1_Load(object sender, System.EventArgs e)
{
hook = new KeyboardHook();
hook.AddFilter(Keys.F, true, false, true);
hook.AddFilter(Keys.F6, false, true, false);
hook.KeyPressed +=new KeyboardHookEventHandler(hook_KeyPressed);
hook.Install();
} private void hook_KeyPressed(object sender, KeyboardHookEventArgs e)
{
this.label1.Text = "Found " + e.KeyStroke.ToString();
}
void hook_KeyPressed(object sender, KeyboardHookEventArgs e)
{
this.label1.Text = "Found " + e.KeyStroke.ToString();
} Full code for this class can be found in the attached ZIP file.
And thanks, again, to Dino Esposito for the inspiration, not to mention blatant plagiarism. :)