0

Problem: I am working on a service which will do some automated processing at a configurable time each night. It does some communication over the internet, formats some information, and creates a file. This file will be used by another program. I don't want to specify what program it is, because I've signed NDAs and I really don't think it's important to the question. My issue is that I cannot get this program to be run by the service. If I run my program as a regular console application, it works fine. I am calling the external program by sending a shell command with the path to the executable and several parameters (for configuration of how it will run and the path to the file I create with my program). My command is correct, as it will run being pasted into a command shell or if my program is run as a console application.

What I've tried: Calling the external program directly from my service (I'm using C# and the Process.Start method, but that's here nor there. I feel my question is more conceptual than my specific implementation). This does nothing. The program I am calling is set to run in an unattended mode (this makes it have no UI or anything). I have tried running a .bat file with the proper command and arguments from my service as well, with no luck (I tested the .bat independently). My service is set to be allowed to interact with the desktop.

My question: How can I get a Windows Service to run an external program? More generically, what is the preferred solution or pattern to use when one must call another process from a Service (Daemon in *nix-land)? If I should be able to call the program and my issue is implementation-specific, I will open a question on StackOverflow. But I would like to know what the standard approach for this problem is.

I know this is supposedly a bad design, because there's a chance there's no user logged in. But the program to be run shouldn't need any special permissions or care about which user it was ran as.

I cannot use the Task Scheduler as this was specifically forbidden in the requirements due to reliability issues. This is actually why the program runs as a service in the first place instead of as a scheduled task.

  • I'm fairly sure I read a similar question a few days ago. Can't find it, though. Maybe it was on SO. – JensG Oct 10 '14 at 23:06
  • You say that the service is allowed to interact with the desktop, but have you verified that the windows account that the service is configured to run under actually have access to run the other program? E.g. by explicitly logging in using those credentials and running the program. When you say 'This does nothing' then what? No exception and zero exit code, or do you gen an exception, or an exit code? Have you redirected the console output of the external process to a log file_ – Pete Feb 22 '16 at 14:58
1

I remember having a similar problem, and it ended up being related to what user is the service running as. It only worked if it was running as a logged in user, as opposed to default Local System. You can specify the user credentials in Services control panel (Log On As), and programmatically as well. The problem with that approach is, that you essentially need to know the user ahead of time and hardcode it. In our case, we ended up forgetting about a service, and replacing it with a regular desktop application, that had no window in taskbar, but an icon in the notification area instead.

  • How did you control the start and stop of the program? And did it just run in an infinite loop? I've tried running as a few different users, but maybe not that one specifically. That does sound annoying having to know the user ahead of time... I'll see if I get any other suggestions and try some stuff out Monday. – dprice Oct 10 '14 at 23:25
  • The program would monitor a folder, and convert/print any file dropped into it, so it was just a FolderWatcher that ran forever. It would get started automatically by putting it in Windows Startup folder. – Eternal21 Oct 10 '14 at 23:35
0

Services are much more reliable for unattended operation than anything else. I have written several, and one that takes arbitrary commands from a registry string to execute (send email usually) upon an event. You need to be careful of user, permissions and paths (use absolute), but here is what the essence of the calls are:

Within my class:

// the action we are supposed to perform
private ProcessStartInfo psi = null;

Parsing options to create process start info:

                int ind = go.ArgIndex;
                if ( ind < args.Length)
                    psi = new ProcessStartInfo(args[ind++]);
                for (; ind < args.Length; ind++) {
                        psi.Arguments = psi.Arguments +       
                            CommandLine.Escape(args[ind]) + " ";
                }

In the service start code (be careful of the difference between service command lines and start arguments):

                Process p = null;
                try {
                    p = Process.Start(psi);
                } catch (InvalidOperationException) {
                    psi.UseShellExecute = false;
                    p = Process.Start(psi);
                }
                p.WaitForExit();

Troubleshoot by making a simple call, no arguments, to an absolute path executable that uses none of stdin, stdout, stderr. Work your way up from there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.