So a couple of days ago I wrote a post on the subject of Outlook and how it locks its PST file, making it impossible for SyncToy to copy it in my nightly backup. I don’t know what Outlook does to put such a bear hug on this file. Lots of other stuff is running and touches files that get backed up just fine. After all, SyncToy just wants to copy it, not change it. But for whatever reason Outlook opens that file when it starts and puts “No Trespassing” signs all over it.
In response I came up with a script that would close Outlook and then execute the sync job. On that a couple of points. First, I stated that I used the NirCmd utility because it allowed the application to close gracefully, which implied that the taskkill command does not. I was wrong about that. If you don’t use the /F switch then taskkill does something similar to NirCmd, which is find the process main window and post a WM_CLOSE (or WM_QUIT, WM_BYEBYE, WM_GTFO, who does windows messages anymore?) to its message queue. I don’t think they use the exact same method, because they seem to behave slightly differently, but whatever. They’re similar.
Second, there is a third way to close Outlook.exe. That is by using the automation interfaces that all the office applications expose. The ProgId of interest is Outlook.Application.
Type outlookAppType = Type.GetTypeFromProgID("Outlook.Application"); object appInstance = Activator.CreateInstance(outlookAppType); appInstance.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, appInstance, null);
That little bit of code will (with some error checking) semi-reliably close Outlook. I say semi-reliably because all these methods seem to occasionally fail for less-than-obvious reasons. Last night in a test the method above failed to close Outlook while it was minimized to the tray, but worked once the window had been restored then minimized again. Go figure.
But even if any of these methods was 100% reliable, and the NirCmd approach seems to come closest, it still won’t work from a service like the task scheduler. I figured this out over a couple of evenings of testing and poking around. The explanation lies in the changes to the way services are launched since Vista/Server 2008/Windows 7. Here is an MS article that discusses the issue. The upshot is that services are launched in window session 0, and the first interactive user logs on to window session 1. The messsage queues are tied to the window session, so there is no way for a service to interact with the user desktop, or post windows messages to windows on that desktop.
There is still a way to mark services as interactive by checking the “Allow service to interact with the desktop” box in the service properties dialog. However at least for Task Scheduler I can confirm that doing so doesn’t enable it to see and post messages to Outlook. exe’s message queue. So for the moment, I am working on a different approach that I may post more about later.