从服务执行shell命令
本文关键字:命令 shell 执行 服务 | 更新日期: 2023-09-27 18:26:59
我正试图从我创建的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
}
}
}
如果是一个需要桌面的windows应用程序,那么您相当于SOL。如果是标准控制台应用程序,则需要重定向标准输入、标准输出和标准错误。您还需要将ProcessStartInfo
的UseShellExecute
属性设置为false
:您的服务无法启动操作系统外壳(cmd.exe
),因为这需要访问桌面。。。此外,不能将该属性设置为true
的标准输入重定向。
标准输入通常连接到键盘。您的服务无法访问键盘。标准输出和标准错误通常连接到cmd.exe
控制台窗口。
一旦您重定向了标准输出和标准错误,您就需要将处理程序连接到以下Process
对象事件:
-
Exited
进程结束时引发 -
OutputDataReceived
当进程将数据写入标准输出时引发(实际上,当输出流上的任何缓冲区都被刷新时就会发生,因此可能会滞后于实际的写入操作) -
ErrorDataReceived
当数据写入标准错误时引发
我倾向于将标准输出和标准错误重定向到同一个流,并确保该流没有缓冲区。它相当于cmd.exe
咒语
some-command 2>&1
将stdout和stderr重定向到同一个文件句柄中。
事实证明,这不起作用的原因是由于应用程序兼容性-会话0隔离。从本质上讲,该服务按预期启动了进程,但它是在会话0内部启动的,因此它对用户是隐藏的,因此,用户无法与它交互
为了绕过这一限制,我能够遵循Pero Matić撰写的《在32位和64位架构中颠覆Vista UAC》指南。这个简短的指南允许我在当前登录用户的会话中从服务生成一个进程,而不是在会话0中。遗憾的是,由于我使用它的项目被取消,我不再有我用来让它工作的完整代码。