【C#学习之路】WMI进程操作实现程序远程更新

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本博客旨在记录学习或开发中遇到的一些问题。
最近需要实现上位机局域网内,在本地和远程实现软件的更新,实际上就是实现本地和远程的文件、进程操作。文件操作好说,直接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)。

在这里插入图片描述

  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值