LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

【C#开发】把dll放在不同的目录让你的程序更整洁

admin
2024年6月6日 10:4 本文热度 1130

程序目录的整理

想必C#的开发者都遇到过这个问题,引用的dll都放在根目录下,随着项目的日益增大,根目录下充满了各种各样的dll,非常的不美观。

如果能够把dll按照想要的目录来存放,那么系统就美观多了,以下是我常用的程序各文件的分布:

  • 【3rdLibs】

    • NLog.dll

    • Newtonsoft.Json.dll

    • ……

  • 【MyLibs】

  • 【Resources】

  • 【Images】

  • Excecutable.exe

  • Excecuteble.exe.config

网上有很多的文章述说这个,比如使用Assembly.Load,但是没有说明在程序中怎么使用,也没有给出具体的代码。这里我结合自己多年的实践经验,再把整个流程和方法详细叙述一遍,以便各位看官有个具体的体会。

系统搜索dll的目录以及顺序

CLR解析一个程序集会在一个根目录内进行搜索,整个探索过程又称Probing,这个根目录很显然就是当前包含当前程序集的目录。

AppDomainSetup这个类存储着探索目录的信息,其成员包括:ApplicationBasePrivateBinPath

程序搜索dll的顺序如下(区分强名称签名的和没有强名称签名的程序集):

没有做强名称签名的程序集:

  • 程序的根目录

  • 根目录下面,与被引用程序集同名的子目录

  • 根目录下面被明确定义为私有目录的子目录

  • 在目录中查找的时候,如果dll查找不到,则会尝试查找同名的exe

  • 如果程序集带有区域性,而不是语言中立的,则还会尝试查找以语言区域命名的子目录

具有强名称签名的程序集:

  • 全局程序集缓存

  • 如果有定义codebase,则以codebase定义为准,如果codebase指定的路径找不到,则直接报告错误

  • 程序的根目录

  • 根目录下面,与被引用程序集同名的子目录

  • 根目录下面被明确定义为私有目录的子目录

  • 在目录中查找的时候,如果dll查找不到,则会尝试查找同名的exe

  • 如果程序集带有区域性,而不是语言中立的,则还会尝试查找以语言区域命名的子目录

如何让程序识别不同目录下的dll?

我们看到,上面的顺序无论是否有强名称签名看,都提到了一个名词“私有目录”

方法一:配置App.config文件的privatePath——【推荐】

这是最简单的方法,当然也有一定的局限性,就是没法对dll做控制,另外,无法解决第三方DllImprt中引入的程序集不在根目录下的问题,不过无论怎么说,这个都基本解决了问题。

配置如下,多个目录用;分隔

<runtime>
	<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
	<probing privatePath="3rdLib;MyLibs;SubFolder\Sub.dll"/>
	 </assemblyBinding></runtime>

方法二:订阅程序集解析事件AssemblyResolve在代码中解析

应用程序集域中支持在程序集解析时的处理:AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;。通过这个事件,我们可以在程序集解析时,根据不同的程序集做不用的处理,比如加载x86的程序集还是64位的程序集,当然也就可以指定程序集目录了

这也正是Assembly.LoadAssembly.LoadFrom等方法的用武之地。

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args){
    AssemblyName assemblyName = new AssemblyName(args.Name);    return Assembly.LoadFrom(Path.Combine(baseDirectory, "3rdLibs"));
}

方法三:在加载使用到dll的代码之前设置重置当前环境的目录

这个方法就是通过Environment.CurrentDirectory=customPath,这样,在调用dll方法时,因为目录已经切换到了
这是一个取巧的方法,不是很实用,要来回切换程序集目录,但是在某些情况下非常好用

如何处理[dllImport]中的程序集的加载

自己写dllImport

如果是自己写,那么久好控制了,可以直接指定相对的目录DllImport(3rdLibs\NLog.dll)。不过这种方法不一定可靠,在某些系统硬是加载不了,如果使用了dllImport还是,推荐下面的另外一种方法。

引用的C#的插件又使用了dllImport

这是很多文章都没有提及的:

因为无法更改路径,那么只能够使用上述特殊的方法,更改当前程序的路径

当然,还有更省事一点的做法,就是在系统环境中,增加一条记录,指向要加载的dll的所在目录。因为C++的代码中,Windows目录和Windows\System32目录以及环境变量设定的目录都是搜索路径之一。

这里提供怎么从C#中修改系统环境变量的代码:

static void AddEnvironmentPaths(IEnumerable<string> paths){    var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };
    string newPath = string.Join(Path.PathSeparator.ToString(), path.Concat(paths));
    Environment.SetEnvironmentVariable("PATH", newPath);
}

参考文章


该文章在 2024/6/6 10:10:37 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved