Having your ASP.NET error handling routine, which sends you emails when an error occurs on your site, itself fail is annoying. Especially when you think you've made the code robust enough. Anyway the error handler for one site I work on was failing with "
ArgumentException: The specified string is not in the form required for a subject".
So what is exactly "the form required for a subject"? Googling for this error message returns a lot of junk and misinformed forum posts. It turns out that setting the Subject on a System.Net.Mail.Message internally calls MailBnfHelper.HasCROrLF (thank you Reflector) which does exactly what it says on the tin. Therefore one forum poster's solution of
subject.Replace("\r\n", " ") isn't going to work when your have either a carriage return or line feed in there.
So, obviously, the solution is:
message.Subject = subject.Replace('\r', ' ').Replace('\n', ' ');
Personally, I think that the MailMessage should to this for you or at least Microsoft should document what actually constitutes a "form required for a subject" in MSDN or, even better, in the actual error message itself!
As Brad Wilson points out one of the nice features of C# 3.0's extension methods is that they work on null instances. Indeed, why shouldn't they? They're just static methods that are invoked in a slightly different way. But this allows a subtle but very pleasing (to me this morning anyway) bit of syntactic sugar for the very commonly used String.IsNullOrEmpty() method.
So instead of:
if (string.IsNullOrEmpty(myString)) ...
you can have the more-readable:
if (myString.IsNullOrEmpty()) ...
public static class StringExtensions
public static bool IsNullOrEmpty(this string str)
It's a very small thing but I like it.
At home, our PC running Vista is rarely rebooted and is either in a low power state sleeping or being used by either me or my wife. One thing we've taken great advantage since the XP days is Fast User Switching which allows someone else to log in to their desktop whilst yours is kept running in the background. My wife and I had got quite used to doing a quick WinKey+L (as you do) before relinquishing control of the PC to one another. In Windows XP WinKey+L is does a "lock workstation" which in non-domain machines takes you back to the Windows logon screen. Unfortunately on Vista it takes you to a "workstation locked" screen, so you then have another mouse click on the Switch User button (followed by monitor re-syncing itself - why does it do this? All users run at the same screen resolution) to take you to the users screen. Of course there is a "Switch User" command tucked away in the little menu next to the lock button on the start menu - but a quick keystroke is what we're after here.
So - I go off searching for a shortcut key that does a "switch user" rather than "lock workstation". After a 20 minutes fruitless Googling for some special key combination, I sat back, thought about it logically and came up with this solution:
- Create a shortcut on your desktop to TSDISCON (* see below) and call it something like "Switch User"
- Go the shortcut Properties page and assign a shortcut key. Note that unfortunately you can't use the Windows Key in your shortcut - so I went for CTRL + ALT + SHIFT + L
- Right click Start button and choose "Open All Users" and move the shortcut into the Programs folder (confirming the UAC prompt as you go).
- Log out, and back in again. This is necessary because Explorer hasn't noticed there's now a shortcut with a new shortcut key it should be taking notice of.
And that did it. CTRL + ALT + SHIFT + L isn't quite a neat as WinKey+L but it's a hell of a lot better than poking around in the Start Menu.
- What is TSDISCON you ask? It's the Terminal Services Disconnect command. Fast User Switching is all made possible by the core Terminal Services technologies which introduced the concept of multiple Window Stations or "sessions" running concurrently on the one machine. It was of course originally designed to support multiple users connecting concurrently to these sessions over the network using the Remote Desktop Protocol (RDP), but Windows XP took advantage of the multi-session architecture to enable Fast User Switching. (The RDP stuff is still there but hobbled to only allow one user to connect at a a time.)
UPDATE: If you don't have tsdiscon.exe on your system for some reason (maybe it's only available in Business/Ultimate or something) then you can use the following C# code (compiled into a Windows EXE using C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe if you don't have Visual Studio) to do the same thing. Tsdiscon.exe is just a wrapper around WTSDisconnectSession. I used Dependency Walker (aka depends.exe) to find out what was being used:
UPDATE 2: For your convenience: I've compiled the below and packaged it into a ZIP along with the source for download here.
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);
const int WTS_CURRENT_SESSION = -1;
static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
static void Main(string args)
throw new Win32Exception();