How to run console application from Windows Service?

Viewed 109635

I have a windows service, written in c# and I need to run a console application from it. Console application also written in c#.

Console application is running fine when it is run not from windows service. When it is ran from ws it doesn`t do anything it should and as it should work for 10-20 seconds I see in debug code is executed at once.

I`m starting my console app with the following code:

proc.Start(fullPathToConsole, args);
proc.WaitForExit();

the path to console is right and when I`m trying to run it from the cmd or just in explorer (without args) it works fine. But after running with the service I see no effect.

I already tried to go to service properties and give it access to desktop and run under both system and my user (also specified in service properties). All remains the same.

ADDITION: I know service do not have ui and I don't want one. I want service to run console application. No need to get any data from it or use this console like ui, just run it to do it`s job.

UPDATE I: discovered, that running calc or any other windows app is easy. But still can`t run cmd or any console app. Actually I need to run it on XP SP2 and Windows 2003 Server. So do not need to interact with Vista in anyway.

Would be glad to any comments!

10 Answers

I use this class:

class ProcessWrapper : Process, IDisposable
{
    public enum PipeType { StdOut, StdErr }

    public class Output
    {
        public string Message { get; set; }
        public PipeType Pipe { get; set; }
        public override string ToString()
        {
            return $"{Pipe}: {Message}";
        }
    }

    private readonly string _command;
    private readonly string _args;
    private readonly bool _showWindow;
    private bool _isDisposed;

    private readonly Queue<Output> _outputQueue = new Queue<Output>();

    private readonly ManualResetEvent[] _waitHandles = new ManualResetEvent[2];
    private readonly ManualResetEvent _outputSteamWaitHandle = new ManualResetEvent(false);

    public ProcessWrapper(string startCommand, string args, bool showWindow = false)
    {
        _command = startCommand;
        _args = args;
        _showWindow = showWindow;
    }

    public IEnumerable<string> GetMessages()
    {
        while (!_isDisposed)
        {
            _outputSteamWaitHandle.WaitOne();
            if (_outputQueue.Any())
                yield return _outputQueue.Dequeue().ToString();
        }
    }

    public void SendCommand(string command)
    {
        StandardInput.Write(command);
        StandardInput.Flush();
    }

    public new int Start()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = _command,
            Arguments = _args,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            RedirectStandardInput = true,
            CreateNoWindow = !_showWindow
        };
        StartInfo = startInfo;

        OutputDataReceived += delegate (object sender, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                _waitHandles[0].Set();
            }
            else if (args.Data.Length > 0)
            {
                _outputQueue.Enqueue(new Output { Message = args.Data, Pipe = PipeType.StdOut });
                _outputSteamWaitHandle.Set();
            }
        };

        ErrorDataReceived += delegate (object sender, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                _waitHandles[1].Set();
            }
            else if (args.Data.Length > 0)
            {
                _outputSteamWaitHandle.Set();
                _outputQueue.Enqueue(new Output { Message = args.Data, Pipe = PipeType.StdErr });
            }
        };

        base.Start();

        _waitHandles[0] = new ManualResetEvent(false);
        BeginErrorReadLine();
        _waitHandles[1] = new ManualResetEvent(false);
        BeginOutputReadLine();

        return Id;
    }

    public new void Dispose()
    {
        StandardInput.Flush();
        StandardInput.Close();
        if (!WaitForExit(1000))
        {
            Kill();
        }
        if (WaitForExit(1000))
        {
            WaitHandle.WaitAll(_waitHandles);
        }
        base.Dispose();
        _isDisposed = true;
    }
}
Related