I’ve been tinkering with a C#-based RSS ScreenSaver for Windows based on the example screensaver project included with the Visual C# Express Studio. Things were going well — despite the fact that I’d never done anything in C# before — until Friday when I tested it on a production box and discovered something … odd.
The way the screensaver is supposed to work is that it snags an RSS feed, and displays the feed items when the screensaver kicks in. Hitting the “Enter” key causes the selected feed item to open up in the user’s default browser. That’s exactly what it does when I test it in the studio and it’s what happens if you choose to “preview” the installed screensaver.
But when the screensaver launches on its own … the “Enter” key stops working. Or more specifically, Windows appears to launch the browser application and then immediately close it. The same thing happens if I specify a non-browser, e.g. “notepad.exe”. If a browser window is already open, it works just fine.
The bit of code that launches the browser is:
I understand what it’s doing (or supposed to be doing) — “rssView.SelectedItem.Link” is a web link, and because of that, Process.Start knows that it should open the link using the default Web browser, in my case Firefox (though the same thing happens with Internet Explorer).
Trying to work through the problem, I tried explictly stating the name of the application I wanted to use to open the url:
The results were the same: the application would launch in studio or preview, but wouldn’t work as a standalone screensaver. Specifying the exact path to IE didn’t work, neither did this:
ProcessStartInfo s = new ProcessStartInfo(“iexplore.exe”);
s.Arguments = rssView.SelectedItem.Link;
All of this led me to experimenting with launching other applications, which is when I discovered that writing “Process.Start(“notepad.exe”)” yields similar results, only in that case I got to see the application launch and then immediately close.
So here I am at Wit’s End, trying to figure out what to do next. My thought was that the program is launching and then immediately ending the process on purpose, but if so, why does it work “correctly” (meaning the way I want it to) in preview and studio? And how do I tell it not to?
It’s All About the Threads
And now I know the answer — it’s all about threads, processes, and child processes. The answer took some digging and luck to find. You see, there are actually two versions of the Microsoft RSS ScreenSaver project out there — the one I started with, and which comes wiht C# Visual Studio, and a second, more advanced version that relies on the new Microsoft Windows RSS platform The documentation for this later version is somewhat cryptically labeled “Screen Saver Sample” but it was the key to understanding the problem:
Take a moment to test out the new feature. Notice that the browser will appear as expected if you launch the screensaver from within the debugger; however, nothing seems to happen if the screensaver is launched from the operating system.
The difference in behavior results from the process that is used to launch the screensaver. Whenever the main screensaver thread exits, the operating system stops any child processes that are still running. When the screensaver is in the Visual Studio debugger, the Internet Explorer process is not linked to it as a child process. However, this is not the case when the screensaver is launched from the Windows Logon Process (Winlogon.exe); the child process has barely enough time to start before it is asked to shut down.
The solution to this dilemma is a new thread. To prevent the screensaver application from exiting until the browser window is closed, call WaitForExit() on the newly created process to wait for the child process to end before continuing. (Don’t forget to close the screensaver form so that the browser is visible!)
This bit of information perfectly explains my problem (which, like so many problems, is obvious in hindsight), but was not included in the original documentation for the screen saver. By modifying the code in this example, I was able get my version of the RSS Screensaver up and running in no time.