5

我正在尝试从我创建的 C# 服务中执行 shell 命令。但是,这个命令似乎没有执行。作为一个标准的控制台应用程序,它工作得很好,所以我知道命令本身或者它是如何在代码中执行的形式没有问题。谁能告诉我为什么这行不通?请记住,我对 C# 还很陌生,所以这可能只是我缺乏经验的问题。以下是服务本身的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;

namespace AdapterDisableTest
{
    class Program : ServiceBase
    {
        //private static Timer workTimer;

        static void Main(string[] args)
        {
            ServiceBase.Run(new Program());
        }

        public Program()
        {
            this.ServiceName = "AdapterDisableTest";
        }

        protected override void OnStart(string[] args)
        {
            base.OnStart(args);

            Process myProcess = new Process();

            myProcess.StartInfo.FileName = @"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe";
            myProcess.StartInfo.Arguments = "controlvm test setlinkstate1 off";
            myProcess.StartInfo.UseShellExecute = false;
            myProcess.StartInfo.CreateNoWindow = true;
            myProcess.Start();

        }

        protected override void OnStop()
        {
            base.OnStop();

            //TODO: clean up any variables and stop any threads
        }

    }
}
4

2 回答 2

0

如果它是一个需要桌面的 Windows 应用程序,那么你几乎就是 SOL。如果是标准控制台应用程序,则需要重定向标准输入、标准输出和标准错误。您还需要将ProcessStartInfo'UseShellExecute属性设置为false:您的服务无法启动 OS shell ( cmd.exe),因为这需要访问桌面……此外,您无法将该属性设置为true.

标准输入通常连接到键盘。您的服务无权访问键盘。标准输出和标准错误通常连接到cmd.exe控制台窗口。

重定向标准输出和标准错误后,您需要将处理程序连接到这些Process对象事件:

  • Exited. 进程结束时引发。
  • OutputDataReceived. 当进程将数据写入标准输出时引发(实际上,在输出流上的任何缓冲区被刷新时发生,因此它可能会滞后于实际的写入操作)。
  • ErrorDataReceived. 当数据写入标准错误时引发。

我倾向于将标准输出和标准错误重定向到同一个流,并确保该流是无缓冲的。相当于cmd.exe咒语

some-command 2>&1

将 stdout 和 stderr 重定向到同一个文件句柄。

于 2013-08-09T16:46:11.010 回答
0

事实证明,这不起作用的原因是Application Compatibility - Session 0 Isolation。本质上,服务按预期启动了进程,但它是在会话 0 内启动的,因此它对用户隐藏,因此用户无法与其交互。

为了绕过这个限制,我可以按照Pero Matić 编写的Subverting Vista UAC in Both 32 and 64 bit Architectures指南进行操作。这个简短的指南允许我从当前登录的用户会话中的服务生成一个进程,而不是在会话 0 中。遗憾的是,我不再拥有完整的代码,我曾经使用它作为我正在使用的项目工作它被取消了。

于 2020-01-30T13:53:54.860 回答