• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

Help with script

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
I have this backup script that shuts down Outlook, runs SyncToy, then restarts Outlook. It runs perfectly when started interactively but doesn't run correctly when scheduled. This is Windows 7 Enterprise, btw.

Code:
@echo off
echo Synchronizing folders...
echo Shutting down Outlook.exe...
"c:\Mark Personal\System Tools\NirCmd\nircmd.exe" closeprocess outlook.exe
:wait
timeout 2
tasklist /FI "IMAGENAME eq outlook.exe" 2>NUL | find /I /N "outlook.exe">NUL
if "&#37;ERRORLEVEL%"=="0" goto :wait
echo Outlook closed; executing SyncToyCmd...
"C:\Program Files\SyncToy 2.1\SyncToyCmd.exe" -R > c:\users\mark\Desktop\Sync.log
echo Sync completed; starting Outlook.exe...
start "" /B /MIN C:\Users\Mark\Desktop\Outlook
echo Outlook.exe started; exiting
@echo on

The scheduler says the task has been run correctly, but the backups aren't happening and the log isn't getting created on the desktop. The task is configured to run as my user, and checking the security logs shows that the logon is succeeding.

When I exec the task manually from the scheduler while logged on as the same user here's what happens:

- task scheduler says the task has been started and gives a pid for cmd.exe
- that pid doesn't show up in task manager unless you click "show processes from all users", even though it is run under my account, and all other processes run under "mark" do show up.
- Outlook doesn't close.
- SyncToy doesn't start, and no log file is written to the desktop.
- The cmd.exe instance doesn't exit cleanly.

Previously I had SyncToy scheduled directly from task scheduler and it worked fine. I added this script to solve the problem of Outlook holding a lock on my mail file. What I assume is happening is that the task scheduler is logging my user onto a hidden window session and running the task in that, but I am not sure why. It further seems that something about the environment in that case is causing the nircmd.exe call to close outlook to fail, and that is parking the script in the wait loop.

Anyone have any ideas?
 
Last edited:
It could definitely be a security issue that's preventing certain commands from running.

Also, it looks like you could have an infinite loop.

Code:
"c:\Mark Personal\System Tools\NirCmd\nircmd.exe" closeprocess outlook.exe
:wait
timeout 2
tasklist /FI "IMAGENAME eq outlook.exe" 2>NUL | find /I /N "outlook.exe">NUL
if "%ERRORLEVEL%"=="0" goto :wait

In this code, if the nircmd fails or syntax fails or any number of reasons where outlook does not go away, you're going to loop forever.

Here's a couple possibilities to correct this:
1) Add a counter and a check so that you only attempt to loop so many times before failing out - something like 10-20 is probably plenty.
2)Add some errorlevel checking after the nircmd.exe, but this does assume that nircmd will return error codes and it also assumes that you can predict what it will do somewhat reliably.

I'm not familiar with nircmd, but you could also just use taskkill unless I'm missing some aspect of what nircmd does.
 
Thanks guys. Yeah I agree it is security. The script is running under my user account, but not elevated, so that is something to try.

On the loop, yeah it could fail to exit. Something that I will get to after I fix this current issue.

Merlin, I believe that what nircmd does differently from taskkill is that it sends a WM_CLOSE message (or one from that family) to the process's main window. So Outlook gets a chance to respond and close the database file properly.
 
A little update. After experimenting with this some more I believe I have it figured out, though I don't have a solution yet.

Turns out you can use taskkill in a manner similar to nircmd, but that neither of them work. Nircmd sends WM_CLOSE to the named process's top-level window. Taskkill sends SIGTERM. Taskkill works for Outlook.exe if its window is open, and Nircmd works all the time, whether the window is open or minimized to the tray. I assume this is because the tray icon is the top-level window for Outlook.exe at that point and gets the message.

However, neither work from Task Scheduler, and the reason appears to be session 0 isolation.

http://www.microsoft.com/whdc/system/sysinternals/Session0Changes.mspx

Because Task Scheduler is a service it is running (and spawning processes) in session 0, while Outlook's UI is running in session 1. So the message queue never sees a message posted from a scheduled task.

Not sure where to go with it at this point. Going to see if there is something I can do from Powershell using automation to tell Outlook to close, rather than a windows message.

Update: the following C# code worked great to close Outlook gracefully...

Code:
Type outlookAppType = Type.GetTypeFromProgID("Outlook.Application");
object appInstance = Activator.CreateInstance(outlookAppType);
appInstance.GetType().InvokeMember("Quit", System.Reflection.BindingFlags.InvokeMethod, null, appInstance, null);

... but only in session 1 running interactively. I guess that's because in session 0 there are no open windows to close. I have another idea for how to solve this, but it's a whole different approach. It sounds like if you want to launch something from task scheduler that can interact with the user session, then you need something in the user session to execute the task.
 
Last edited:
Try using "CMD /C {whatever exe you want to run}" (without the quotes)

It'll run the process in a separate shell / command interpreter and maintains your stacks better.

More docs for this in "cmd /?"

Good Luck
 
Doesn't task scheduler have a specific option to allow tasks to interact with the desktop?

It used to, and I guess that would mean running the task in session 1, but I didn't see it in the task properties in the Windows 7 scheduler GUI.
 
It used to, and I guess that would mean running the task in session 1, but I didn't see it in the task properties in the Windows 7 scheduler GUI.

Another follow-up on this. I had to poke around a bit to remind myself what Nothinman was referring to. The option to interact with the desktop isn't on the scheduled task, but rather on the service itself.

I checked the Schedule service properties, and it is not selected to interact with the desktop. Moreover, I can't change any of the properties for the schedule service in the GUI, or using sc from the command line. The options are disabled in the GUI, and the sc returns access denied for any attempt to interact with the schedule service. This occurs whether cmd is run as admin or not.

Anyone know whether the properties for the schedule service can be changed somehow? I looked in the registry and located the service entry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule, but I am not sure enough of what I'm looking at yet to attempt any changes.
 
Here's a link to the issue.

At the very end of the article, they discuss a registry keywhich controls the effect of the SERVICE_INTERACTIVE_PROCESS flag.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\NoInteractiveServices

From the article:

The NoInteractiveServices value defaults to 0, which means that services with SERVICE_INTERACTIVE_PROCESS are allowed to run interactively. When NoInteractiveServices is set to a nonzero value, no service started thereafter is allowed to run interactively, regardless of whether it has SERVICE_INTERACTIVE_PROCESS.

I don't know if this will help you or not (I don't have access to Windows 7 here at work) but I'm certainly interested in this because I spend a large part of my day writing services.

I'm still digging to find an answer to your earlier question.

Dave
 
Here's a link to the issue.

At the very end of the article, they discuss a registry keywhich controls the effect of the SERVICE_INTERACTIVE_PROCESS flag.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\NoInteractiveServices

From the article:

The NoInteractiveServices value defaults to 0, which means that services with SERVICE_INTERACTIVE_PROCESS are allowed to run interactively. When NoInteractiveServices is set to a nonzero value, no service started thereafter is allowed to run interactively, regardless of whether it has SERVICE_INTERACTIVE_PROCESS.

I don't know if this will help you or not (I don't have access to Windows 7 here at work) but I'm certainly interested in this because I spend a large part of my day writing services.

I'm still digging to find an answer to your earlier question.

Dave

Thanks, Dave. That article is relevant, and I stumbled on it once earlier. My working assumption is that if I can get the task scheduler service to run interactively, then my techniques for closing Outlook should work because the script will execute on session 1.

Unfortunately I still haven't figured out how to alter the configuration properties for the schedule service. It seems like they wanted to lock that up. If I figure out which key directs the service to run in session 1 I may find I can't edit it.

The other issue is that both Vista and 7 actually use the task scheduler for system tasks, and I'm not sure whether directing it to run in session 1 will have any side-effects I don't want.

I'm really resisting the idea of a third-party scheduler, but I have thought of writing a little user-task bootstrapper that sits in session 1 and listens on a named pipe for a command string.
 
Another update. I located a post by an MVP that divulged the appropriate registry key to set the schedule service to run interactively.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule

Under that key is a value named "Type" which is a bit mask. Setting bit 8 (0x100) marks the service as running interactively. After backing up the key I modded the value and restarted, and the schedule service was indeed marked as running interactively.

But none of the methods of closing Outlook worked. Not sure what to conclude from this other than that setting that bit isn't enough to get the service running in session 1 where it can see Outlook's window.

At this point I pretty much believe there is no solution within the task scheduler framework for any of these methods of closing Outlook. Will need to come up with another approach.
 
Back
Top