提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本博客旨在记录学习或开发中遇到的一些问题。
最近需要实现上位机局域网内,在本地和远程实现软件的更新,实际上就是实现本地和远程的文件、进程操作。文件操作好说,直接File.Copy()就好,本地进程操作使用Process()即可实现,主要是远程进程操作我多方查阅后使用WMI实现。
提示:以下是本篇文章正文内容,下面案例可供参考
一、WMI是什么?
Windows 管理规范(Windows Management Instrumentation)是一项核心的 Windows 管理技术;用户可以使用 WMI 管理本地和远程计算机。WMI 通过编程和脚本语言为日常管理提供了一条连续一致的途径。
例如,用户可以:
· 在远程计算机器上启动一个进程。
· 设定一个在特定日期和时间运行的进程。
· 远程启动计算机。
· 获得本地或远程计算机的已安装程序列表。
· 查询本地或远程计算机的 Windows 事件日志。
二、使用步骤
1.引入库
对于.net平台语言,即C#语言,则要使用System.Management域相关功能与下层通信。
using System.Management;
2.连接到WMI
代码:
public async Task ConnectWMIAsync()
{
await Task.Run(() =>
{
//ManagementScope类能够建立和远程计算机(或者本地计算机)的WMI连接,表示管理可操作范围
ManagementScope Ms = new ManagementScope();
string targetIP = model.TargetPath.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries)[0];
ManagementPath RemoteNameSpace = new ManagementPath($@"\\{targetIP}\root\cimv2");
//ConnectionOptions 为建立的WMI连接提供所需的所有设置
ConnectionOptions connOP = new ConnectionOptions();
//设定用于WMI连接操作的用户名
connOP.Username = model.UserName;
//设定用户的口令
connOP.Password = model.PassWord;
Ms.Path = RemoteNameSpace;
Ms.Options = connOP;
//连接到实际操作的WMI范围
Ms.Connect();
});
}
如果没报错,那就恭喜你!连接成功了!但是大多数情况下可能会出现的异常就是“拒绝访问”,这可是当时把我折磨的死去活来,很有可能是目标计算机的相关权限没有设置好,感谢这位大佬的博客解决了我的问题:
https://www.cnblogs.com/bonelee/p/16539667.html
用代码调试时总会很慢,可以先用Windows自带的工具调试WMI能否连接成功,命名空间中的内容就是 new ManagementPath是传入的参数:
连接成功:
注意:WMI不能连接本地
3.打开与关闭进程
本地进程
/// <summary>
/// 打开一个本地进程
/// </summary>
public void CreatLocalProcess()
{
string path = Path.Combine(model.ExePath, model.Name);
Process process = new Process();
process.StartInfo.FileName = path;
process.Start();
}
/// <summary>
/// 关闭一个本地进程
/// </summary>
public void RemoveLocalProcess()
{
//关闭当前程序的进程,App.exe
string path = Path.Combine(model.ExePath, model.Name);
Process[] pp = Process.GetProcessesByName(path);
for (int j = 0; j < pp.Length; j++)
{
pp[j].Kill();
}
}
远程进程
要打开远程进程比较麻烦,使用“schtasks”在远程计算机上创建一个打开程序的定时任务,然后再立即执行这个任务,任务执行完毕后再删除这个任务。
/tn 计划任务的名字 /tr调用程序的路径 /sc设置执行频率 /F强制删除任务
/// <summary>
/// 打开一个远程进程
/// </summary>
/// <param name="model"></param>
public void CreatRemoteProcess()
{
//建立对远程的进程操作对象
ManagementClass processClass = new ManagementClass(Ms, new ManagementPath("Win32_Process"), null);
//获得用来提供参数的对象
ManagementBaseObject inParams = processClass.GetMethodParameters("Create");
inParams["CommandLine"] = "schtasks /delete /tn \"cid\" /F";
//删除任务
ManagementBaseObject outParams1 = processClass.InvokeMethod("Create", inParams, null);
//(只能启动进程,没有UI界面)
//inParams["CommandLine"] = "F://CID//Line//CID.Line.exe";
string path = Path.Combine(model.ExePath, model.Name);
inParams["CommandLine"] = $"schtasks /create /tn cid /tr F:\\CID\\Main\\CID.Main.exe /sc once /st 11:11";
//创建任务
//创建任务
ManagementBaseObject outParams2 = processClass.InvokeMethod("Create", inParams, null);
inParams["CommandLine"] = "schtasks /run /tn \"cid\"";
//执行任务
ManagementBaseObject outParams3 = processClass.InvokeMethod("Create", inParams, null);
inParams["CommandLine"] = "schtasks /delete /tn \"cid\" /F";
//删除任务
ManagementBaseObject outParams4 = processClass.InvokeMethod("Create", inParams, null);
关闭远程进程就很简单不用使用任务了:
/// <summary>
/// 关闭一个远程进程
/// </summary>
/// <param name="model"></param>
public void RemoveRemoteProcess()
{
//ObjectQuery类或其派生类用于在ManagementObjectSearcher中指定查询。
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process");
//WQL语句,设定的WMI查询内容和WMI的操作范围,检索WMI对象集合
ManagementObjectSearcher searcher = new ManagementObjectSearcher(Ms, query);
ManagementObjectCollection returnCollection = searcher.Get();
foreach (ManagementObject service in returnCollection)
{
if (service["Name"].ToString() == model.Name)
{
object[] obj = new object[] { 0 };
service.InvokeMethod("Terminate", obj);
break;
}
}
}
4.程序更新
就是简单的复制更新File.Copy();
总结
谢谢你阅读到这里!希望会对你有所帮助。
完整的程序是用WPF的MVVM模式实现的,也是我正在学习部分,完整代码有需自取(转到github)。