Thursday, December 31, 2015

The Sluggish Three Finger Salute

Not So Shortcuts

Like many of you I recently upgraded both my portable and my primary workstation to Windows 10. Unlike some of you I did this willingly, having heard that this release of Windows was significantly improved from v8.1 (which I did not install) and because I do like to stay on top of the platform for my clients that will be using it.

Shortly after installing the upgrade, and having gone through some painful changes and learning curves, I noticed that my Windows shortcut keys were responding very sluggishly. As a developer and keyboard enthusiast I have quite a number of shortcut keys defined at the OS level. For example Ctrl-Alt-U will pop up my trust copy of UltraEdit, Ctrl-Alt-Q will fire up SQL Server Management Studio, Ctrl-Alt-X for Excel. You get the picture.

I hadn't seen this sluggish shortcut behavior in Windows 7 and it was immensely frustrating. Almost all my applications are on SSD drives and I'm running a quad-core i7 CPU so they should be flying up on the screen! It had to be something OS-specific. So I employed a little Google-Fu to determine the cause of the problem.

My research uncovered a fair amount about how the shortcut key system operates and how Window 8 and 10 Metro apps behave. This question and answer on SuperUser gives a concise synopsis of the root problem, which is that some Windows processes don't behave well, especially newer "Metro" apps. When closing these apps they remain memory-resident and eventually become "tombstoned", which apparently means they are taking up memory but not responding to many Windows messages. I assume they respond to a request to be restarted though.

That SuperUser entry led me to this excellent article from Raymond Chen of Microsoft that indicated how Windows locates the program that should receive the shortcut key. It will first cycle through all existing processes to see if its the owner of the shortcut key. The problem is that some processes do not respond to the Windows message in a timely fashion, causing the delay. How inconsiderate.

Having learned about the cause of the problem the issue became a detective case — how to track down the inconsiderate processes. I started with the suggestions in the SuperUser post with some success but the problem kept reappearing. I don't have time to pore through my Task Manager processes a couple of times a day to track down every ill-behaved program. I needed some way to identify the offending processes quickly.

Being a fan of the "quick-and-dirty" utility I fired up Visual Studio (using a shortcut key) and put together a quick console application that will enumerate the top-level Windows processes and query each for the hot key. The code is shown below.


This is a pretty brute-force approach to the problem but appears to work. I coded it to query the windows in a multi-threaded fashion but in practice that probably wasn't necessary. The response time to the SendMessageTimeout API call is in very small fractions of seconds, frequently sub-millisecond, so the multi-threading probably adds unnecessary overhead. I'm not to keen to refactor it because it works fast enough for me at the moment.

The process calls the EnumWindows API method to loop through all the top level windows that are currently running. Some of these are low-level processes that are not important for our purposes but I didn't want to exclude anything that might be relevant. The EnumWindows method takes as a parameter a callback method that will be executed once for each window located. This is handled using a defined delegate signature that is used with inline method invocation. Within that method I start a thread for a process that will discover the window's associated name and hot key.

The QueryHotKey method will first query the window for its name. The name may not be accessible for a variety of reasons, the most likely of which is accessibility. If not available I just list it as such rather than go to great lengths to determine the process information. In most cases the cause of the shortcut key delay will be something more mundane for which the name is available.

The heart of the utility is the call to SendMessageTimeout API method. This will send a Windows message to the window to query their shortcut key, with the stipulated timeout in milliseconds. My research led me to believe that Windows 8/10 waits three seconds before moving on so I used the same value.

Once the windows list has been exhausted I wait for the threads to complete, then output the results to the console. In practice I ran this from a command line and used good old command line output redirection to spool the results to a file, which I can view in Notepad or any other text editor to find the culprit(s).

Do I Really Need Calc To Stay Resident?

So I ran my code, which worked pretty much correctly on the first pass, a situation definitely unusual for me. I needed some minor additions to the results and got what I needed.

What it uncovered was pretty interesting. The two processes that were causing the problem for me were newer Windows apps, that is the Windows Calculator and the Windows Settings app. I had opened both of them earlier and closed them but they remain resident in a hibernated state that does not respond to some messages, apparently. I will admit that I'm no expert on the structure of these newer apps and their "tombstoned" state. I'll leave that commentary to those more knowledgeable than me.

Once I killed the tasks I tried a shortcut key and sure enough my text editor sprang immediately to life. Hooray! However, the problem reoccurs when I start one of the apps that remains a background task. If you check out Andy Geisler's reply to the SuperUser question he lists some tips for prohibiting this behavior, and this page has a step-by-step tutorial on how to disable various Windows background apps. For me, disabling Store and Settings appears to have been the most effective.

Thursday, April 9, 2015

Sending Mail Via SMTP Over Implicit SSL in .Net

My Kingdom for Port 25

I recently ran across a situation where I wanted my home workstation to send emails on a periodic basis. No problem, I'm a developer, so I'll just whip up a quick .Net console application and set it to run as a scheduled task when I want to transmit the necessary information.

All was well and good until I checked my log files and found quite a few SMTP send errors. How strange. I use log4net for logging in most of my work so I tailed the log file using the excellent LogView Plus utility. From that I was able to determine that the send utility only failed when my workstation was connected to my client's VPN. And so the plot thickened.

Like most of you readers my ISP, a major carrier in the northeastern United States, blocks traffic on port 25 as an anti-spam method. The only SMTP server that can be reached is the ISP's own server and only if you're connected to their network. However, when connected to my client's VPN the SMTP traffic was being routed over their network and my ISP's mail server would reject the connection since it looks like an unauthorized relay attempt.

My domain has a mail server that I can use but I can't reach it via the normal port 25 access because of the aforementioned ISP blocking. However the server can be reached via port 465 if transmitting over SSL. This port is no longer specifically for SMTPS but it works with my mail server so if I adjust a few settings in my code I should be fine. How typically naive of me.

Explicit Implications

So I modified my code that connects to the SMTP server to send to look like this:

When execution got to the Send method there was a long wait, then an exception. I wasn't connected to the VPN but clearly something had timed out. The error indicated a failure sending mail (duh!) with the additional inner exception "Unable to read data from the transport connection: net_io_connectionclosed" (huh?!?).

After much head scratching I was able to determine that the mail server, when monitoring port 465, is expecting all traffic over that port to be encrypted using SSL. That means the certificate negotiation happens even before the first SMTP HELO command. Further research indicated that the SmtpClient class does not support this type of transport level security, called Implicit SSL. So what's the point of the SmtpClient EnableSsl property? It turns out that uses a different certificate negotiation procedure. The client connects via an insecure port, specifically the dreaded port 25, and issues a STARTTLS command. The client and server will then negotiate the secure transmission after the explicit request, hence the name Explicit SSL. But this didn't help my situation because port 25 is being blocked by my ISP. Grrrrrr! Even if I tried to use Explicit SSL it wouldn't work because I can't reach my mail server over that port.

Tunnel My Way To Freedom

So I needed some way to send via SMTP over a secure connection that was negotiated before the initial SMTP handshake. I checked various Open Source libraries but they all support only Explicit SSL. I really didn't want to invest a lot of time rolling my own SMTPS implementation (although it would be an interesting project), especially since this was supposed to be a quickie utility.

What I finally located was a utility called Stunnel. It's essentially a secure transport connection between two endpoints. You can use it on a client to redirect traffic to a port to another server/port combination.

DISCLAIMER: Stunnel uses portions of the OpenSSL library, which recently had a high-profile exploit published in all major tech news media. I believe the latest version uses the patched OpenSSL but please use at your own risk.

Once the utility is installed, you use the "stunnel Service Install" entry on the Start Menu to set it up as a service. Before starting the service you need to make a modification to the "stunnel.conf" configuration file. The entry for my particular situation looked like this:

; ************** Example SSL client mode services

[my-smtps]
client = yes
accept = 127.0.0.1:465
connect = mymailserver.com:465

This tells stunnel to accept traffic locally on port 465 and reroute it over a secure channel to my public mail server, A slight change to my code:


...was all I needed to make this work.

The upside of all this was I learned a good deal about SMTP. The downside is that this "quickie" utility took a lot longer than I expected, proving once again that there is no such thing as a "quickie" utility.