栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用并排程序集加载DLL的x64或x32版本

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用并排程序集加载DLL的x64或x32版本

我创建了一个简单的解决方案,能够从编译为AnyCPU的可执行文件中加载特定于平台的程序集。使用的技术可以总结如下:

  1. 确保默认的.NET程序集加载机制(“ Fusion”引擎)找不到平台特定程序集的x86或x64版本
  2. 在主应用程序尝试加载特定于平台的程序集之前,请在当前AppDomain中安装自定义程序集解析器
  3. 现在,当主应用程序需要特定于平台的程序集时,Fusion引擎将放弃(由于步骤1)并调用我们的自定义解析器(由于步骤2);在自定义解析器中,我们确定当前平台,并使用基于目录的查找来加载适当的DLL。

为了演示该技术,我将附带一个简短的基于命令行的教程。我在Windows XP x86和Vista SP1
x64上测试了生成的二进制文件(通过复制二进制文件,就像您的部署一样)。

注1 :“ csc.exe”是C尖锐的编译器。本教程假定它在您的路径中(我的测试使用的是“ C: WINDOWS Microsoft.NET
framework v3.5 csc.exe”)

注意2 :建议您为测试创建一个临时文件夹,然后运行其当前工作目录设置为该位置的命令行(或powershell),例如

(cmd.exe)C:mkdir TEMPCrossPlatformTestcd TEMPCrossPlatformTest

步骤1 :特定于平台的程序集由一个简单的C#类库表示:

// file 'library.cs' in C:TEMPCrossPlatformTestnamespace Cross.Platform.Library{    public static class Worker    {        public static void Run()        { System.Console.WriteLine("Worker is running"); System.Console.WriteLine("(Enter to continue)"); System.Console.ReadLine();        }    }}

步骤2 :我们使用简单的命令行命令编译特定于平台的程序集:

(cmd.exe from Note 2)mkdir platformx86csc /out:platformx86library.dll /target:library /platform:x86 library.csmkdir platformamd64csc /out:platformamd64library.dll /target:library /platform:x64 library.cs

步骤3 :主程序分为两部分。“ Bootstrapper”包含可执行文件的主要入口点,它在当前appdomain中注册一个自定义程序集解析器:

// file 'bootstrapper.cs' in C:TEMPCrossPlatformTestnamespace Cross.Platform.Program{    public static class Bootstrapper    {        public static void Main()        { System.AppDomain.CurrentDomain.AssemblyResolve += CustomResolve; App.Run();        }        private static System.Reflection.Assembly CustomResolve( object sender, System.ResolveEventArgs args)        { if (args.Name.StartsWith("library")) {     string fileName = System.IO.Path.GetFullPath(         "platform\"         + System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")         + "\library.dll");     System.Console.WriteLine(fileName);     if (System.IO.File.Exists(fileName))     {         return System.Reflection.Assembly.LoadFile(fileName);     } } return null;        }    }}

“程序”是应用程序的“实际”实现(请注意,在Bootstrapper.Main的末尾调用了App.Run):

// file 'program.cs' in C:TEMPCrossPlatformTestnamespace Cross.Platform.Program{    public static class App    {        public static void Run()        { Cross.Platform.Library.Worker.Run();        }    }}

步骤4 :在命令行上编译主应用程序:

(cmd.exe from Note 2)csc /reference:platformx86library.dll /out:program.exe program.cs bootstrapper.cs

步骤5 :我们现在完成了。我们创建的目录的结构应如下所示:

(C:TEMPCrossPlatformTest, root dir)    platform (dir)        amd64 (dir) library.dll        x86 (dir) library.dll    program.exe    *.cs (source files)

如果现在在32位平台上运行program.exe,则将加载platform x86
library.dll;否则,将运行DLL。如果您在64位平台上运行program.exe,将加载platform amd64
library.dll。请注意,我在Worker.Run方法的末尾添加了Console.ReadLine(),以便您可以使用任务管理器/进程资源管理器来调查已加载的DLL,或者可以使用Visual
Studio / Windows调试器将其附加到进程中以查看调用堆栈等

运行program.exe时,我们的自定义程序集解析器将附加到当前的appdomain。.NET一旦开始加载Program类,它就会看到对“库”程序集的依赖,因此它将尝试加载它。但是,找不到这样的程序集(因为我们已将其隐藏在platform
/ 子目录中)。幸运的是,我们的自定义解析器知道我们的诡计,并基于当前平台尝试从适当的platform / 子目录加载程序集。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/382361.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号