我正在尝试从我创建的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
}
}
}
答案 0 :(得分:0)
如果它是需要桌面的Windows应用程序,那么你就是SOL。如果它是标准控制台应用程序,则需要重定向标准输入,标准输出和标准错误。您还需要将ProcessStartInfo
的{{1}}属性设置为UseShellExecute
:您的服务无法启动操作系统shell(false
),因为它需要访问桌面。 ..此外,您无法将标准输入重定向到该属性设置为cmd.exe
。
标准输入通常连接到键盘。您的服务无法访问键盘。标准输出和标准错误通常连接到true
控制台窗口。
重定向标准输出和标准错误后,您需要将处理程序连接到这些cmd.exe
对象事件:
Process
。在流程结束时提升。Exited
。当进程将数据写入标准输出时引发(实际上,当输出流上的任何缓冲区被刷新时发生,因此它可能会滞后于实际写入操作)。OutputDataReceived
。在将数据写入标准错误时触发。我倾向于将标准输出和标准错误重定向到同一个流,并确保该流是无缓冲的。它相当于ErrorDataReceived
咒语
cmd.exe
将stdout和stderr重定向到同一个文件句柄。
答案 1 :(得分:0)
事实证明,此操作不起作用的原因是Application Compatibility - Session 0 Isolation。本质上,该服务按预期启动了该过程,但由于它是在会话0内启动的,因此对用户隐藏了,因此用户无法与之交互。
为了解决这个限制,我能够遵循PeroMatić编写的指南Subverting Vista UAC in Both 32 and 64 bit Architectures。这份简短的指南使我能够从当前登录的用户会话内(而不是会话0内)从服务中生成一个进程。可悲的是,我不再拥有用来使它作为我正在使用的项目工作的完整代码。取消了。