Windows服务更改批处理文件中回显/流重定向的行为

时间:2014-05-28 13:07:05

标签: c# batch-file cmd windows-services

创建Windows批处理文件c:\ test \ first.bat:

@echo off
echo A
call second.bat < empty.txt
echo B
echo C

和两个空文件c:\ test \ second.bat和c:\ test \ empty.txt (如果它们不是空的,也会发生同样的情况。)

运行first.bat。正如预期的那样,输出是

A
B
C

现在,不是直接运行批处理文件,而是创建一个C#命令行应用程序:

using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var processInfo = new ProcessStartInfo("cmd.exe", @"/c c:\test\first.bat");
            processInfo.CreateNoWindow = true;
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardError = true;
            processInfo.RedirectStandardOutput = true;
            var process = new Process();
            process.EnableRaisingEvents = true;
            var log = new BlockingCollection<string>();
            process.OutputDataReceived += (sender, e) => log.Add(e.Data);
            process.Exited += (sender, e) =>
            {
                process.Dispose();
                File.WriteAllText(@"c:\test\log.txt", string.Join("\n", log));
            };
            process.StartInfo = processInfo;
            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            process.WaitForExit();
        }
    }
}

同样,正如预期的那样创建了文件c:\ test \ log.txt并包含

A
B
C

现在,不是命令行应用程序,而是创建Windows服务:

using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;

namespace WindowsService1
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
            this.CanStop = true;
        }

        protected override void OnStart(string[] args)
        {
            var processInfo = new ProcessStartInfo("cmd.exe", @"/c c:\test\first.bat");
            processInfo.CreateNoWindow = true;
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardError = true;
            processInfo.RedirectStandardOutput = true;
            var process = new Process();
            process.EnableRaisingEvents = true;
            var log = new BlockingCollection<string>();
            process.OutputDataReceived += (sender, e) => log.Add(e.Data);
            process.Exited += (sender, e) =>
            {
                process.Dispose();
                File.WriteAllText(@"c:\test\slog.txt", string.Join("\n", log));
            };
            process.StartInfo = processInfo;
            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
        }

        protected override void OnStop()
        {
        }
    }
}

安装并启动服务(允许所有相关文件所需的权限)。 (这个服务使用哪个帐户(用户,本地服务,本地系统......)似乎并不重要。)

再次创建文件c:\ test \ slog.txt,但现在它包含:

A
echo B
B
echo C
C

为什么?


(也许相关:如果&#34之后没有换行符; echo C&#34;在first.bat中,slog.txt包含:

A
echo B
B
more?

为什么?)

1 个答案:

答案 0 :(得分:1)

(评论中提供的解决方案。转换为社区维基答案。请参阅Question with no answers, but issue solved in the comments (or extended in chat)

@Gennadiy写道:

  

尝试添加processInfo.RedirectStandardInput = true;

OP写道:

  

是的,这使得服务的行为更像我的预期。知道为什么吗?使用它有什么缺点吗?

@Harry Johnston写道:

  

当批处理器没有有效的标准输入流时,看起来会遇到麻烦。我想象一旦重定向到empty.txt完成后,它尝试将标准输入句柄设置回原始(无效)值时会发生根本问题。