Windows services 使用TeamCity停止和重新启动远程主机上的服务的最佳方法?
好的,我不能完全决定这是不是最好在ServerFault上问,但我认为这更多的是一个编程问题的核心…(你可能不同意) 我试图将各种各样的部署活动打包到一个控制台应用程序中,然后使用TeamCity build命令行运行程序使用适当的参数执行它。然而,试图在远程计算机上停止/启动/安装Windows服务似乎是一项棘手的任务,从无法使用提升权限运行的进程中使用ServiceController 此时,在每个远程主机上使用Invoke命令执行Powershell脚本实际上可能是最简单的方法。(当然,允许这是一个不同的安全漏洞)比禁用UAC或其他选项Windows services 使用TeamCity停止和重新启动远程主机上的服务的最佳方法?,windows-services,teamcity,Windows Services,Teamcity,好的,我不能完全决定这是不是最好在ServerFault上问,但我认为这更多的是一个编程问题的核心…(你可能不同意) 我试图将各种各样的部署活动打包到一个控制台应用程序中,然后使用TeamCity build命令行运行程序使用适当的参数执行它。然而,试图在远程计算机上停止/启动/安装Windows服务似乎是一项棘手的任务,从无法使用提升权限运行的进程中使用ServiceController 此时,在每个远程主机上使用Invoke命令执行Powershell脚本实际上可能是最简单的方法。(当然,允
是否有人愿意大胆地提出一个意见,认为什么方法是最好的继续进行的方法?好的,我创建了一个基于Powershell的服务控制器类,允许应用程序在没有提升权限的情况下运行,以控制远程服务 这是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace PowershellBasedServiceControl
{
// All the relevant bits came from this article: http://www.codeproject.com/KB/cs/HowToRunPowerShell.aspx
// if script execution fails, try running 'Enable-PSRemoting' using Powershell as an admin on the target host
public class PowershellServiceController
{
public bool StartService(string serviceName, string remoteHost)
{
return StartService(serviceName, remoteHost, String.Empty, String.Empty);
}
public bool StartService(string serviceName, string remoteHost, string remoteUserName, string remotePassword)
{
bool result = false;
string execOutput = ExecuteScript(BuildStartServiceScript(serviceName, remoteHost, remoteUserName, remotePassword, false));
result = execOutput.StartsWith("0");
if (!result)
Console.WriteLine(execOutput);
return result;
}
public bool StopService(string serviceName, string remoteHost)
{
return StopService(serviceName, remoteHost, String.Empty, String.Empty);
}
public bool StopService(string serviceName, string remoteHost, string remoteUserName, string remotePassword)
{
bool result = false;
string execOutput = ExecuteScript(BuildStopServiceScript(serviceName, remoteHost, remoteUserName, remotePassword, false));
result = execOutput.StartsWith("0");
if (!result)
Console.WriteLine(execOutput);
return result;
}
string ExecuteScript(string scriptText)
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection<PSObject> results = pipeline.Invoke();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
string BuildStartServiceScript(string serviceName, string remoteHost, string remoteUserName, string remotePassword, bool echoScript)
{
StringBuilder script = new StringBuilder();
if (!String.IsNullOrEmpty(remoteUserName))
{
script.AppendLine("$block = {");
script.AppendLine("$returnCode = 1");
script.AppendLine("try {");
script.AppendLine(String.Format("$service = \"{0}\"", serviceName));
script.AppendLine("$serviceController = (new-Object System.ServiceProcess.ServiceController($service,\"localhost\"))");
script.AppendLine("if($serviceController.Status -notlike 'Running') {");
script.AppendLine("$serviceController.Start()");
script.AppendLine("$serviceController.WaitForStatus('Running',(new-timespan -seconds 120))");
script.AppendLine("if ($serviceController.Status -eq 'Running') { ");
script.AppendLine("$returnCode = 0 }");
script.AppendLine("} else { ");
script.AppendLine("$returnCode = 0 } }");
script.AppendLine("catch {");
script.AppendLine("return 1");
script.AppendLine("exit }");
script.AppendLine("return $returnCode}");
script.AppendLine("");
script.AppendLine(String.Format("$pass = convertto-securestring \"{0}\" -asplaintext -force", remotePassword));
script.AppendLine(String.Format("$mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist \"{0}\",$pass", remoteUserName));
script.AppendLine(String.Format("$res = Invoke-Command -computername \"{0}\" -Credential $mycred -scriptblock $block", remoteHost));
script.AppendLine("return $res");
}
if (echoScript)
Console.WriteLine(script.ToString());
return script.ToString();
}
string BuildStopServiceScript(string serviceName, string remoteHost, string remoteUserName, string remotePassword, bool echoScript)
{
StringBuilder script = new StringBuilder();
if (!String.IsNullOrEmpty(remoteUserName))
{
script.AppendLine("$block = {");
script.AppendLine("$returnCode = 1");
script.AppendLine("try {");
script.AppendLine(String.Format("$service = \"{0}\"", serviceName));
script.AppendLine("$serviceController = (new-Object System.ServiceProcess.ServiceController($service,\"localhost\"))");
script.AppendLine("if($serviceController.Status -notlike 'Stopped') {");
script.AppendLine("$serviceController.Stop()");
script.AppendLine("$serviceController.WaitForStatus('Stopped',(new-timespan -seconds 120))");
script.AppendLine("if ($serviceController.Status -eq 'Stopped') { ");
script.AppendLine("$returnCode = 0 }");
script.AppendLine("} else { ");
script.AppendLine("$returnCode = 0 } }");
script.AppendLine("catch {");
script.AppendLine("return 1");
script.AppendLine("exit }");
script.AppendLine("return $returnCode}");
script.AppendLine("");
script.AppendLine(String.Format("$pass = convertto-securestring \"{0}\" -asplaintext -force", remotePassword));
script.AppendLine(String.Format("$mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist \"{0}\",$pass", remoteUserName));
script.AppendLine(String.Format("$res = Invoke-Command -computername \"{0}\" -Credential $mycred -scriptblock $block", remoteHost));
script.AppendLine("return $res");
}
if (echoScript)
Console.WriteLine(script.ToString());
return script.ToString();
}
}
希望其他人会觉得这很有用。似乎powershell脚本应该是解决这一问题的好方法。也在寻找示例。@Andrew Orsich:请参阅我在下面发布的示例,谢谢。安德鲁·奥里希:我修复了生成停止脚本时的一个错误。另外,最初的“WaitFor…”调用似乎在生产中造成了问题,所以我删除了它们。
class Program
{
static void Main(string[] args)
{
PowershellServiceController runner = new PowershellServiceController();
if (runner.StartService("w3svc", "myremotehost.com", "myusername", "mypassword"))
Console.WriteLine("Service was started successfully");
else
Console.WriteLine("Failed to start remote service");
Console.WriteLine("Press ENTER to quit");
Console.ReadLine();
}
}