这里安装windows服务我们用sc命令,这里需要远程服务器IP,服务名称、显示名称、描述以及执行文件,安装后需要验证服务是否安装成功,验证方法可以直接调用ServiceController来查询服务,也可以通过远程注册表来查找服务的执行文件;那么卸载文件我们也就用SC命令了,卸载后需要检测是否卸载成功,修改显示名称和描述也用sc命令。至于停止和启动Windows服务我们可以用sc命令也可以用ServiceController的API,当停止失败的时候我们会强制杀掉远程进程,在卸载windows 服务我们需要关闭windows服务窗口,不然无法删除服务(服务被标记为已删除状态)。注意安装和卸载Windows服务是通过sc命令来执行的,把sc命令发送到服务器上,服务器需要一段执行时间,所以在远程注册表不一定马上体现安装和卸载的效果,这里我们需要有一个重试的机制。远程服务需要引用System.ServiceProcess,关闭远程进程需要引用 System.Management.dll 。先关code如下:

   #region Windows Service 操作
/// <summary>
/// 安装Windows 服务
/// </summary>
/// <param name="serviceEXEPath">可执行文件的完全路径</param>
public void Install(string webIp, string serviceName, string displayName, string description, string serviceEXEPath)
{
//检查安装文件是否存在
string remoteFile = PathUtil.GetRemotePath(webIp, serviceEXEPath);
if (!File.Exists(remoteFile))
{
throw new Exception($"安装文件{serviceEXEPath}在服务器{webIp}上不存在");
}
//生成安装指令
string serviceInstallCommand = $"sc \\\\{webIp} create {serviceName} binpath= \"{serviceEXEPath}\" displayname= \"{displayName}\" start= auto ";
string updateDescriptionCommand = $"sc \\\\{webIp} description {serviceName} \"{description}\" ";
string[] cmd = new string[] { serviceInstallCommand, updateDescriptionCommand };
string ss = Cmd(cmd);
//检查安装是否成功
string imagePath = GetImagePath(webIp, serviceName);
int retryTime = ;
int maxTime = ;
while (retryTime < maxTime && string.IsNullOrEmpty(imagePath))
{
Thread.Sleep( * );
retryTime++;
imagePath = GetImagePath(webIp, serviceName);
}
if (string.IsNullOrEmpty(imagePath))
{
throw new Exception($"{serviceName}在{webIp}安装失败,{ss}");
}
} /// <summary>
/// 卸载Windows 服务
/// </summary>
/// <param name="serviceEXEPath">可执行文件的完全路径</param>
public void Uninstall(string webIp, string serviceName, string serviceEXEPath)
{
//关闭mmc.exe进程,如果windows 服务打开 将无法卸载
var ps = Process.GetProcessesByName(@"mmc", webIp);
if (ps.Length > )
{
CloseProcess(webIp, "mmc.exe", string.Empty);
} //检查卸载文件是否存在
string remoteFile = PathUtil.GetRemotePath(webIp, serviceEXEPath);
if (!File.Exists(remoteFile))
{
throw new Exception($"卸载文件{serviceEXEPath}在服务器{webIp}上不存在");
} //生成卸载命令
string[] cmd = new string[] { $"sc \\\\{webIp} stop {serviceName}", $"sc \\\\{webIp} delete {serviceName}" };
string ss = Cmd(cmd);
string imagePath = GetImagePath(webIp, serviceName);
//检查卸载是否成功
int retryTime = ;
int maxTime = ;
while (retryTime < maxTime && !string.IsNullOrEmpty(imagePath))
{
Thread.Sleep( * );
retryTime++;
imagePath = GetImagePath(webIp, serviceName);
}
if (!string.IsNullOrEmpty(imagePath))
{
throw new Exception($"{serviceName}在{webIp}卸载失败,{ss}");
}
} /// <summary>
/// 修改windows 服务的显示名称和描述
/// </summary>
/// <param name="webIp"></param>
/// <param name="serviceName"></param>
/// <param name="displayName"></param>
/// <param name="description"></param>
public void UpdateDisplayNameAndDescription(string webIp, string serviceName, string displayName, string description)
{
//检查服务是否存在
string imagePath = GetImagePath(webIp, serviceName);
if (string.IsNullOrEmpty(imagePath))
{
throw new Exception($"服务{serviceName}在{webIp}不存在");
}
//生成修改指令
string updateDispalyNameCommand = $"sc \\\\{webIp} config {serviceName} displayname= \"{displayName}\"";
string updateDescriptionCommand = $"sc \\\\{webIp} description {serviceName} \"{description}\" ";
string[] cmd = new string[] { updateDispalyNameCommand, updateDescriptionCommand };
string ss = Cmd(cmd);
} /// <summary>
/// sc 停止和启动windows服务
/// </summary>
/// <param name="webIp"></param>
/// <param name="serviceName"></param>
/// <param name="stop"></param>
public void StopAndStartService(string webIp, string serviceName, bool stop)
{
string serviceCommand = $"sc \\\\{webIp} {(stop ? "stop" : "start")} {serviceName}";//停止或启动服务
string[] cmd = new string[] { serviceCommand };
string ss = Cmd(cmd);
} /// <summary>
/// 运行CMD命令
/// </summary>
/// <param name="cmd">命令</param>
/// <returns></returns>
public string Cmd(string[] cmd)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.AutoFlush = true;
for (int i = ; i < cmd.Length; i++)
{
p.StandardInput.WriteLine(cmd[i].ToString());
}
p.StandardInput.WriteLine("exit");
string strRst = p.StandardOutput.ReadToEnd();
p.WaitForExit();
p.Close();
return strRst;
} /// <summary>
/// 关闭远程计算机进程
/// </summary>
/// <param name="webIp"></param>
/// <param name="processName"></param>
public void CloseProcess(string webIp, string processName, string executablePath)
{
ConnectionOptions oOptions = new ConnectionOptions();
oOptions.Authentication = AuthenticationLevel.Default;
ManagementPath oPath = new ManagementPath($"\\\\{webIp}\\root\\cimv2");
ManagementScope oScope = new ManagementScope(oPath, oOptions);
ObjectQuery oQuery = new ObjectQuery($"Select * From Win32_Process Where Name = \"{processName}\"");
using (ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oScope, oQuery))
{
foreach (ManagementObject oManagementObject in oSearcher.Get())
{
if (oManagementObject["Name"].ToString().ToLower() == processName.ToLower())
{
/*
foreach (PropertyData prop in oManagementObject.Properties)
{
Console.WriteLine($" {prop.Name} -- - {prop.Value } ");
}
*/
string path = oManagementObject["ExecutablePath"].ToString();
if (string.IsNullOrEmpty(executablePath) || path == executablePath)
{
oManagementObject.InvokeMethod("Terminate", new object[] { });
}
}
}
}
} /// <summary>
/// 获取远程计算机 服务的执行文件
/// </summary>
/// <param name="serverIP">远程计算机IP</param>
/// <param name="serviceName">远程服务名称</param>
/// <returns></returns>
public string GetImagePath(string serverIP, string serviceName)
{
string registryPath = @"SYSTEM\CurrentControlSet\Services\" + serviceName;
using (RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, serverIP).OpenSubKey(registryPath))
{
if (key == null)
{
return string.Empty;
}
string value = key.GetValue("ImagePath").ToString();
key.Close();
value = value.Trim('"');
if (value.Contains("SystemRoot"))
{
return ExpandEnvironmentVariables(serverIP, value);
}
return value;
}
} /// <summary>
/// 替换路径中的SystemRoot
/// </summary>
/// <param name="serverIP">远程计算机IP</param>
/// <param name="path">路径</param>
/// <returns></returns>
private string ExpandEnvironmentVariables(string serverIP, string path)
{
string systemRootKey = @"Software\Microsoft\Windows NT\CurrentVersion\";
using (RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, serverIP).OpenSubKey(systemRootKey))
{
string expandedSystemRoot = key.GetValue("SystemRoot").ToString();
key.Close();
path = path.Replace("%SystemRoot%", expandedSystemRoot);
return path;
}
} /// <summary>
/// 停止或启动Windows 服务
/// </summary>
/// <param name="serviceName">服务名称</param>
/// <param name="serverIP">远程IP</param>
/// <param name="stop">是否是停止</param>
public void StopAndStartWindowsService(string serviceName, string serverIP, bool stop)
{
using (ServiceController sc = ServiceController.GetServices(serverIP)
.FirstOrDefault(x => x.ServiceName == serviceName))
{
if (sc == null)
{
throw new Exception($"{serviceName}不存在于{serverIP}");
}
StopAndStartWindowsService(sc, stop); if (stop)
{
sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(, , ));
}
sc.Close();
} } /// <summary>
/// 停止或启动Windows 服务
/// </summary>
/// <param name="sc"></param>
/// <param name="stop"></param>
private void StopAndStartWindowsService(ServiceController sc, bool stop = true)
{
Action act = () =>
{
ServiceControllerStatus serviceSate = sc.Status;
if (stop && (serviceSate == ServiceControllerStatus.StartPending || serviceSate == ServiceControllerStatus.Running))
{
//如果当前应用程序池是启动或者正在启动状态,调用停止方法
sc.Stop();
}
if (!stop && (serviceSate == ServiceControllerStatus.Stopped || serviceSate == ServiceControllerStatus.StopPending))
{
sc.Start();
}
};
int retryCount = ;
int maxCount = ;
while (sc != null && retryCount <= maxCount)
{
try
{
act();
break;
}
catch (Exception ex)
{
if (stop)
{
string serverIP = sc.MachineName;
string serviceName = sc.ServiceName;
var imeagePath = GetImagePath(serverIP, serviceName);
FileInfo fileInfo = new FileInfo(imeagePath);
CloseProcess(serverIP, fileInfo.Name, fileInfo.FullName);
}
retryCount++;
if (retryCount == maxCount)
{
throw new Exception($"{(stop ? "停止" : "启动")}Windows服务{sc.ServiceName}出错{ex.Message}");
}
Thread.Sleep( * );
}
}//end while
} /// <summary>
/// 获取windows 服务状态
/// </summary>
/// <param name="serviceName">服务名称</param>
/// <param name="serverIP">服务器IP</param>
/// <returns></returns>
public ServiceControllerStatus GetServiceState(string serviceName, string serverIP)
{
ServiceControllerStatus serviceSate;
using (ServiceController sc = ServiceController.GetServices(serverIP)
.FirstOrDefault(x => x.ServiceName == serviceName))
{
if (sc == null)
{
throw new Exception($"{serviceName}不存在于{serverIP}");
}
serviceSate = sc.Status;
sc.Close();
}
return serviceSate;
} #endregion

C# 远程服务器 安装、卸载 Windows 服务,读取远程注册表,关闭杀掉远程进程的更多相关文章

  1. 用命令 安装/卸载 windows服务(转)

    第一种方法: 1. 开始 ->运行 ->cmd 2. cd到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727(Framework版本号按IIS配置 ...

  2. 二种方法安装卸载Windows服务的命令

    第一种方法:通过Dos命令安装系统服务1. 开始 运行输入 cmd 进入dos窗口2. cd命令进入到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727目录下, ...

  3. 安装&卸载Windows服务

    使用.NET Framework的工具InstallUtil.exe. 安装服务 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.e ...

  4. 批处理文件安装与卸载Windows服务

    //安装Windows服务 将RECPost.exe和RECPostService替换成自己的项目名称和服务名称,并将文件保存成bat格式.其中%cd%是获取相对路径 @echo off set fi ...

  5. 使用InstallUtil安装及卸载Windows服务的具体操作 Visual Studio 2012版本

    关于Visual Studio 2012中使用InstallUtil对Windows服务进行安装与卸载的文章,在MSDN中的http://msdn.microsoft.com/en-us/librar ...

  6. 【先定一个小目标】Redis 安装成windows服务-开机自启

    1.第一步安装成windows服务的,开机自启动 redis-server --service-install redis.windows.conf 2.启动\关闭 redis-server --se ...

  7. 【C#】使用bat文件安装卸载Window服务

    1.安装服务 @echo off @title 安装windows服务path %SystemRoot%\Microsoft.NET\Framework\v4.0.30319echo========= ...

  8. Redis是可以安装成windows服务-开机自启

    其实Redis是可以安装成windows服务的,开机自启动,命令如下 redis-server --service-install redis.windows.conf 安装完之后,就可看到Redis ...

  9. MongoDB安装成为Windows服务及日常使用遇到问题总结

    安装MongoDB: http://blog.csdn.net/liuzhoulong/article/details/6124566 严格按照上面的步骤,设置数据库目录,设置日志目录,安装服务.可是 ...

随机推荐

  1. react之自定义迷你redux的实现

    export function createStore(reducer){ let currentState={} let currentListeners=[] function getState( ...

  2. Java char

    Java  char字符判断和操作方法类似C的ctype库 //: object/Shifting.java package object; import static net.util.Print. ...

  3. poj1015 01二维背包

    /* 给定辩控双方给每个人的打分p[i],d[i], dp[j][k]表示前i个人有j个被选定,选定的人的辩控双方打分差之和是k,此状态下的最大辩控双方和 按01背包做,体积一维是1,体积二维是辩控双 ...

  4. hdu3015树状数组 poj1990的离散化版本

    都是一类题目,推导调试比较烦,想出来还是不难的 /* 给定n个点对,按一维升序排序一次,每个点的序号为Di,按二维升序排序一次,每个点的序号为Hi 求sum{w(i,j)} w(i,j)=abs(Di ...

  5. python 全栈开发,Day38(在python程序中的进程操作,multiprocess.Process模块)

    昨日内容回顾 操作系统纸带打孔计算机批处理 —— 磁带 联机 脱机多道操作系统 —— 极大的提高了CPU的利用率 在计算机中 可以有超过一个进程 进程遇到IO的时候 切换给另外的进程使用CPU 数据隔 ...

  6. 《LINQ技术详解C#》-5.非延迟操作符

    1.转换操作符 1.ToArray 从一个类型为T的输入序列创建一个类型为T的数组. 2.ToList 从一个类型为T的序列创建一个类型为T的列表. 3.ToDictionary 从类型为T的序列创建 ...

  7. hdu 1253 3维迷宫 在规定时间内能否出迷宫 (3维BFS)

    题意:有一个人要在魔王回来之前逃出城堡.1表示墙,0表示路.魔王将在T分钟后回到城堡 起点可以是墙,但是人能走出.而终点也可以是墙,那自然就走不出了,但是要判断. 剪枝:如果终点是门或者从起点到终点的 ...

  8. day8--socket网络编程进阶

    socket:socket就是实现服务器和客户端数据的交换,服务器端接收并发送数据,客户端发送并接收数据,并且需要注意的是,在python3中,socket值接收字节.因为客户端在发送连接给服务器的时 ...

  9. BZOJ1966 [Ahoi2005]VIRUS 病毒检测 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1966 题意概括 现在有一些串和一个病毒模板.让你统计非病毒串的总数.串个数<=500. 串由 ...

  10. 移动端Tap与滑屏实战技巧总结以及Vue混合开发自定义指令

    最近在忙混合开发,因交互相对复杂,所以也踩了很多坑.在此做一下总结. 1.tap事件的实际应用 在使用tap事件时,老生常谈的肯定是点透问题,大多情况下,在有滑屏交互的页面时,我们会在根节点阻止默认行 ...