我需要从内部网站远程停止和启动服务,但是启动/停止服务需要冒充有权这样做的用户。
我正在使用System.Diagnostics.Process
以另一个用户身份运行一个进程,然后使用参数调用sc.exe
来执行此操作并监听标准输出。
当我运行sc query
时,它可以正常工作,并向我返回与在命令行上运行时相同的信息。但是,当我运行sc停止或启动时,它给了我错误
[SC] OpenService失败1060:指定的服务不存在 已安装的服务。
奇怪的是,我用完全相同的服务名称调用了sc query
,它发现服务很好并且完美地返回了状态。
如果我运行该进程正在运行的sc start
命令,并从我的本地命令提示符处执行此命令,则它会正常工作。使用上面的Process运行时,它只会给出1060错误
代码(Exists方法有效,Stop方法无效)
public ManualWindowsServiceController(string serviceName, string machineName, string serviceAccountName, string serviceAccountPassword)
{
_serviceName = serviceName;
_machineName = machineName;
_serviceAccountName = serviceAccountName;
_securePassword = new SecureString();
foreach (var c in serviceAccountPassword)
_securePassword.AppendChar(c);
}
public void StopService()
{
var process = RunCommand("stop");
if (process == null) throw new InvalidOperationException($"Could not get service status for {_serviceName}");
while (!process.StandardOutput.EndOfStream)
{
var line = process.StandardOutput.ReadLine();
}
}
public bool Exists()
{
var process = RunCommand("query");
if (process == null) return false;
while (!process.StandardOutput.EndOfStream)
{
var line = process.StandardOutput.ReadLine();
if (line != null && line.ToLower().Contains("does not exist")) return false;
}
return true;
}
private Process RunCommand(string command)
{
var arguments = $"\\\\{_machineName} {command} {_serviceName}";
var psi = new ProcessStartInfo
{
FileName = "sc.exe",
WorkingDirectory = @"c:\",
Arguments = arguments,
UserName = _serviceAccountName,
Password = _securePassword,
Domain = "MyDomain",
CreateNoWindow = false,
UseShellExecute = false,
RedirectStandardOutput = true, WindowStyle = ProcessWindowStyle.Maximized
};
return Process.Start(psi);
}