如何在 C# 中的 Windows 服务中执行批处理脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5999169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:51:15  来源:igfitidea点击:

How can I execute a batch script in a windows service in C#?

c#windowswindows-servicesbatch-file

提问by Frank Flannigan

I'm trying to execute a .bat script in a C# windows service but it doesn't seem to be working.

我正在尝试在 C# windows 服务中执行 .bat 脚本,但它似乎不起作用。

So the script I am trying to execute, startup.bat, in turn calls another script, call catalina.bat ..., which in turn executes start java ...

所以我试图执行的startup.bat脚本,反过来调用另一个脚本,call catalina.bat ...然后执行start java ...

I can execute startup.bat manually but I want to run it as a Windows service. When I try to do that in a C# windows service application, nothing seems to happen. My Windows service code looks like this:

我可以手动执行 startup.bat 但我想将它作为 Windows 服务运行。当我尝试在 C# windows 服务应用程序中执行此操作时,似乎没有任何反应。我的 Windows 服务代码如下所示:

public class MyService : ServiceBase
{
    public static void Main(string[] args)
    {
        ServiceBase.Run(new MyService());
    }

    protected override void OnStart(string[] args)
    {
        base.OnStart(args);
        this.RunScript(@"bin\startup.bat");
        Thread.Sleep(1000);
    }

    protected override void OnStop()
    {
        base.OnStop();
        this.RunScript(@"bin\shutdown.bat");
        Thread.Sleep(1000);
    }

    private void RunScript(string processFileName)
    {
        var startInfo = new ProcessStartInfo
        {
            FileName = "cmd.exe",
            Arguments = "/C " + Path.Combine(@"C:\server", processFileName),
            CreateNoWindow = true,
            ErrorDialog = false,
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            UseShellExecute = false,
            WindowStyle = ProcessWindowStyle.Hidden
        };

        startInfo.EnvironmentVariables.Add("CATALINA_HOME", @"c:\server");

        var process = new Process();
        process.StartInfo = startInfo;
        process.Start();
    }
}

I don't understand why this doesn't execute. What am I doing wrong?

我不明白为什么这不执行。我究竟做错了什么?

And yes, you may notice I'm trying to launch Tomcat on Windows as a service with C#. Well I'm doing that because I haven't been able to use tomcat7.exe for various reasons but it's probably better to not ask why I'm doing such things. Whatever the reason is, what I'm doing here should also work, shouldn't it?

是的,您可能会注意到我正在尝试在 Windows 上启动 Tomcat 作为使用 C# 的服务。好吧,我这样做是因为由于各种原因我无法使用 tomcat7.exe,但最好不要问我为什么要这样做。不管是什么原因,我在这里所做的也应该有效,不是吗?

Update in response to Gabe's suggestion:

更新响应 Gabe 的建议:

If I set UseShellExecute = true I get an exception:

如果我设置 UseShellExecute = true 我得到一个异常:

System.InvalidOperationException: The Process object must have the UseShellExecute property set to false in order to redirect IO streams.
    at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
    at System.Diagnostics.Process.Start()
    at MyService.RunScript(String processFileName)

So I set RedirectStandardError and RedirectStandardOutput to false, which yields this error:

因此,我将 RedirectStandardError 和 RedirectStandardOutput 设置为 false,从而产生此错误:

System.InvalidOperationException: The Process object must have the UseShellExecute property set to false in order to use environment variables.
  at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
  at System.Diagnostics.Process.Start()
  at MyService.RunScript(String processFileName)

argh! I feel exasperated!

啊!我觉得很气愤!

采纳答案by Frank Flannigan

To close the loop on this, the problem was indeed Windows security permission issues.

为了结束这个循环,问题确实是 Windows 安全权限问题。

The suggestion made hereseemed to resolve my issue.

提出的建议在这里似乎解决我的问题。

回答by Richard Schneider

Run "cmd.exe" and pass "startup.bat" as an argument.

运行“cmd.exe”并将“startup.bat”作为参数传递。

回答by YetAnotherUser

Try setting "Allow service to interact with desktop" in your service setting.

尝试在您的服务设置中设置“允许服务与桌面交互”。

Possible duplicate - Run Batch-Files in Windows Service while logged off

可能重复 -注销时在 Windows 服务中运行批处理文件

回答by Tom Pickles

Try:

尝试:

FileName = "%comspec%",
Arguments = "/C " + Path.Combine(@"C:\server", processFileName),

回答by David Heffernan

If your script runs fine as an interactive user but not as a service then there are a couple of obvious possible causes:

如果您的脚本作为交互式用户运行良好,但不能作为服务运行,那么有几个明显的可能原因:

  1. Your service is running under a user account that is unable to perform the actions in the script.
  2. Your script tries to interact with the desktop but can't because of session 0 isolation.
  1. 您的服务在无法执行脚本中操作的用户帐户下运行。
  2. 您的脚本尝试与桌面交互,但由于会话 0 隔离而无法进行。

These suggestions are essentially guesses but with so little information it's hard to do better.

这些建议基本上是猜测,但由于信息太少,很难做得更好。