.Net Framework中的AppDomain.AssemblyResolve事件的常见用法、问题,以及解决办法( 二 )


四、解决办法一种解决办法是喊话对应的软件开发商让修改 。不过也许对应的开发商已经跑路,或的确做了修改,但用户侧仍然用了未修改前的旧版本 , 这种方式是不可靠的 。       问题解决思路:        通过反射拿到承载AppDomain.AssemblyResolve事件的Delegate , 逐一检查Delegate中各ResolveEventHandler是否正常,不正常者关小黑屋后改造后再置入AppDomain.AssemblyResolve事件的Delegate 。               附例程:
 1         class AssemblyResolveHook 2         { 3             ResolveEventHandler _handler; 4             const string c_no_this_assembly = "NoThisAssembly, Version=1.0.0.0, Culture=zh-CN, PublicKeyToken=null"; 5 6             AssemblyResolveHook(ResolveEventHandler handler) 7             { 8                 _handler= handler; 9             }1011             Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)12             {13                 if (_handler== null) {14                     return null;15                 }1617                 // 这里是“小黑屋”改造过程18                 // 此处是对症下药的较温和的无害的处理方式19                 var asm = args.RequestingAssembly;20                 var asm2 = _handler(sender, args);21                 if (asm2 != null && asm != null && asm.FullName == asm2.FullName) {22                     asm2 = null;23                 }2425                 return asm2;26             }2728             /// <summary>29             /// 使调用本方法之前的所有CurrentDomain_AssemblyResolve事件响应无害化30             /// </summary>31             public static void Handsup()32             {33                 try {34                 var domain = AppDomain.CurrentDomain;35                 var far = domain.GetFieldValue("_AssemblyResolve") as ResolveEventHandler;36                 if (far != null) {37                     var invocationList = far.GetInvocationList();38                     var num = invocationList.Length;39                     for (int i = 0; i < num; i++) {40                         var handler = (ResolveEventHandler)invocationList[i];4142                         // 测试一下这个handler有没有问题?43                         // 方法是给一个不可能找到的程序集名称,看是否返回了程序集,如果是,给关小黑屋44                         var asm = handler(domain, new ResolveEventArgs(c_no_this_assembly, System.Reflection.Assembly.GetExecutingAssembly()));45                         if (asm != null) {46                             handler = new ResolveEventHandler(new AssemblyResolveHook(handler).CurrentDomain_AssemblyResolve);47                         }4849                         far = i == 0 ? handler : (ResolveEventHandler)Delegate.Combine(far, handler);50                     }5152                     domain.SetFieldValue("_AssemblyResolve", far);53                     }54                 }55                 catch (System.Exception ex) {56                     System.Diagnostics.Debug.WriteLine(ex.ToString());57                 }58             }59         }

推荐阅读