使用反射检查程序集,实现自动更新

使用反射检查程序集,实现自动更新

在.Net下要让程序实现自动维护程序集的版本并且实现自动更新到最新版本的功能,可以使用反射机制。它提供了检查程序集的方法,通过 System.Reflection 中的 Assembly 类我们可以加载程序集,然后检查它的版本号,以此判断是否需要下载或更新。这里我写了一个示例来实现这个功能。但最后发现一旦加载了程序集就占用了需要更新的程序集文件,导致文件替换失败。为了解决这个问题,我参考了Flier's SkyAssembly.UnloadWayfarer's Prattle通过应用程序域AppDomain加载和卸载程序集。下面就是我的代码,由于时间仓促,估计有些异常还没有处理到。请大家指教。

  1using System;
  2using System.IO;
  3using System.Reflection;
  4using System.Collections.Generic;
  5using System.Text;
  6
  7namespace Update
  8{
  9    // 序列化这个用来传递参数的类
 10    public class AssembliyInf : MarshalByRefObject
 11    {
 12        public string AssemblyName = "";
 13        public string AssemblyFileFullPath = "";
 14        public string Version = "";
 15        public string Revision = "";
 16        public string Major = "";
 17        public string Minor = "";
 18    }

 19
 20    // 由于是远程调用的方式,所以这个类也需要序列化
 21    public class AssemblyLoader : MarshalByRefObject, IDisposable
 22    {
 23        public AssembliyInf GetAssemblyInf(string fileFullName)
 24        {
 25            AssembliyInf assemblyInf = new AssembliyInf();
 26
 27            try
 28            {
 29                Assembly assembly = Assembly.ReflectionOnlyLoadFrom(fileFullName);
 30
 31                assemblyInf.AssemblyName = ((AssemblyName)assembly.GetName()).Name;
 32                assemblyInf.AssemblyFileFullPath = assembly.Location;
 33                assemblyInf.Version = ((AssemblyName)assembly.GetName()).Version.ToString();
 34                assemblyInf.Revision = ((AssemblyName)assembly.GetName()).Version.Revision.ToString();
 35                assemblyInf.Major = ((AssemblyName)assembly.GetName()).Version.Major.ToString();
 36                assemblyInf.Minor = ((AssemblyName)assembly.GetName()).Version.Minor.ToString();
 37
 38                assembly = null;     // 释放引用
 39
 40                // 手工调用框架的垃圾收集器
 41                System.GC.Collect();
 42                System.GC.WaitForPendingFinalizers();
 43                System.GC.Collect(0);
 44            }

 45            catch (Exception)
 46            {
 47            }

 48            return assemblyInf;
 49        }

 50
 51        public void Dispose()
 52        {
 53        }

 54    }

 55
 56
 57
 58    class Program
 59    {
 60        static void Main(string[] args)
 61        {
 62            Console.WriteLine();
 63            string sourceFile, distinationFile;
 64
 65            sourceFile = @"D:\MyApp\Update\myApp.exe";          // 假定准备更新的程序集已经下载到本地
 66            distinationFile = @"D:\MyApp\myApp.exe";            // 这是要维护的目标程序集,发现新版本后就需要替换
 67
 68            // 显示准备更新的程序集信息
 69            AssembliyInf assemblyNew = GetAssemblyInf(sourceFile);
 70            ShowAssembly(assemblyNew);
 71
 72            // 显示当前使用的程序集信息
 73            AssembliyInf assemblyCurrent = GetAssemblyInf(distinationFile);
 74            ShowAssembly(assemblyCurrent);
 75
 76            // 比较两个程序集
 77            if (Compare(assemblyNew, assemblyCurrent))
 78            {
 79                Console.WriteLine("需要更新当前程序集!");
 80                // 开始更新
 81                Update(assemblyNew, assemblyCurrent);
 82            }

 83            else
 84                Console.WriteLine("不需要更新当前程序集!");
 85
 86            Console.ReadKey();
 87        }

 88
 89        // 用新的程序集替换现有的
 90        static void Update(AssembliyInf assemblyNew, AssembliyInf assemblyCurrent)
 91        {
 92            string sourceFile, distinationFile;
 93
 94            sourceFile = assemblyNew.AssemblyFileFullPath;
 95            distinationFile = assemblyCurrent.AssemblyFileFullPath;
 96
 97            // 替换文件
 98            File.Copy(sourceFile, distinationFile, true);
 99
100        }

101
102        // 显示程序集相关信息
103        static void ShowAssembly(AssembliyInf assembly)
104        {
105            Console.WriteLine("Assembly Name:             " + assembly.AssemblyName );
106            Console.WriteLine("Assembly Version.Current:  " + assembly.Version);
107            Console.WriteLine("Assembly Version.Revision: " + assembly.Revision);
108            Console.WriteLine("Assembly Version.Major:    " + assembly.Major);
109            Console.WriteLine("Assembly Version.Minor:    " + assembly.Minor);
110            Console.WriteLine("Assembly FullName:         " + assembly.AssemblyFileFullPath);
111            Console.WriteLine();
112        }

113
114        // 比较两个程序集判断是否需要更新
115        static bool Compare(AssembliyInf assemblyNew, AssembliyInf assemblyCurrent)
116        {
117            if ((assemblyNew.AssemblyName == assemblyCurrent.AssemblyName) 
118                && (int.Parse(assemblyNew.Revision) > int.Parse(assemblyCurrent.Revision)))
119                return true;
120            else
121                return false;
122        }

123
124        // 获取程序集的信息
125        static AssembliyInf GetAssemblyInf(string fileFullName)
126        {
127            AssembliyInf assemblyInf = new AssembliyInf(); 
128
129            string dllName = typeof(Program).Assembly.Location;
130            AppDomain domain = null;
131            AppDomainSetup setup = new AppDomainSetup();
132            setup.ShadowCopyFiles = "true";
133            domain = AppDomain.CreateDomain(dllName, null, setup);
134            AssemblyLoader al = (AssemblyLoader)domain.CreateInstanceFromAndUnwrap(dllName, "Update.AssemblyLoader");
135            AssembliyInf tmpAssemblyInf = al.GetAssemblyInf(fileFullName);
136            
137            // 由于使用了序列化导致传回的对象不能传出这个方法,所以要转换一下
138            assemblyInf.AssemblyName = tmpAssemblyInf.AssemblyName;
139            // 又因为是使用了子程序域的方法,实际执行加载的子程序域是一个临时文件。返回值是一个临时文件。
140            //assemblyInf.AssemblyFileFullPath = tmpAssemblyInf.AssemblyFileFullPath;
141            assemblyInf.AssemblyFileFullPath = fileFullName;
142            assemblyInf.Version = tmpAssemblyInf.Version;
143            assemblyInf.Major = tmpAssemblyInf.Major;
144            assemblyInf.Minor = tmpAssemblyInf.Minor;
145            assemblyInf.Revision = tmpAssemblyInf.Revision;
146
147            AppDomain.Unload(domain);
148
149            return assemblyInf;
150        }

151    }

152
153}

154
原文地址:https://www.cnblogs.com/eric1394/p/520819.html