Toggle navigation
首页
产品中心
全新RDIF.vNext低代码框架
镇店
.NET C/S开发框架
.NET Web敏捷开发框架
.NET 快速开发框架(全新EasyUI版本)
.NET 代码生成器
.NET WebAPI服务端开发框架
客户案例
付款方式
国思学堂
技术文章
新闻资讯
下载
关于
首页
技术文章
RDIF.NET
正文
原创
2020-04-18
浏览 (
8808
)
.NET分离exe和dll在不同的目录让你的程序更整洁
# 1、引言 在一个项目开发中一般都是把引用的dll放在根目录下,随着项目的日益增大,根目录下的dll文件就会越来越多,合理规划这些dll的存放地址,可以使整个项目更加的规范与美观。这篇文章就为大家介绍关于C#如何在指定文件夹寻找文件dll的相关内容,文中通过基于RDIFramework框架WinForm版为基础进行介绍,Web的相关dll规划类似,希望对大家具有一定的参考学习价值。 我们框架原执行目录下的dll存放如下,可以看到整个目录下的文件非常多。 ![原框架运行目录结构](http://doc.rdiframework.net/blog/article/20200418180242401.png-pw) 下面我们通过最常用的方式对dll文件进行规划处理,使整个运行目录更加的干净,规范,最终效果如下图所示。 ![框架运行目录规划后的结构](http://doc.rdiframework.net/blog/article/20200418180317982.png-pw) 可以看到,上图的整个运行目录结构非常的清爽与整洁了。如何实现的呢?下面我们就具体讲解。 # 2、实现方法 ## 2.1、系统搜索dll的目录以及顺序 CLR解析一个程序集会在一个根目录内进行搜索,整个探索过程又称Probing,这个根目录很显然就是当前包含当前程序集的目录。 AppDomainSetup这个类存储着探索目录的信息,其成员包括:ApplicationBase、PrivateBinPath。 程序搜索dll的顺序如下(区分强名称签名的和没有强名称签名的程序集): **没有做强名称签名的程序集:** > 1. 程序的根目录 > 2. 根目录下面,与被引用程序集同名的子目录 > 3. **根目录下面被明确定义为私有目录的子目录** > 4. 在目录中查找的时候,如果dll查找不到,则会尝试查找同名的exe > 5. 如果程序集带有区域性,而不是语言中立的,则还会尝试查找以语言区域命名的子目录 **具有强名称签名的程序集:** > 1. 全局程序集缓存 > > 2. 如果有定义codebase,则以codebase定义为准,如果**codebase指定的路径找不到,则直接报告错误** > > 3. 程序的根目录 > > 4. 根目录下面,与被引用程序集同名的子目录 > > 5. **根目录下面被明确定义为私有目录的子目录** > > 6. 在目录中查找的时候,如果dll查找不到,则会尝试查找同名的exe > > 7. 如果程序集带有区域性,而不是语言中立的,则还会尝试查找以语言区域命名的子目录。如下图所示: > ![程序集信息](http://doc.rdiframework.net/blog/article/20200418180408778.png-pw) ## 2.2、如何让程序识别不同目录下的dll? 我们看到,上面的顺序无论是否有强名称签名,都会用到**私有目录**,要实现程序识别不同目录下的dll文件,一般有三种方式。 > 1、配置App.config文件的privatePath——【推荐】。 > > 2、订阅程序集解析事件AssemblyResolve在代码中解析。 > > 3、在加载使用到dll的代码之前重置当前环境的目录。 ### 2.2.1、配置App.config文件的privatePath——【推荐】 这是最简单最常用的方法,也是我们采用的方式。这儿要说明的是此方法有一定的局限性,就是没法对dll做控制,另外无法解决第三方`DllImprt`中引入的程序集不在根目录下的问题。配置如下,多个目录用;分隔。 ```xml <configuration> <runtime> <!--xmlns是必需的特性。指定程序集绑定所需的 XML 命名空间。 使用字符串“urn: 架构-microsoft-com:asm.v1”作为值。--> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <publisherPolicy apply="yes"/> <!--指定运行时是否使用发布者策略--> <!--指定加载程序集时公共语言运行时搜索的子目录, 其中privatePath是相对于*.exe.config文件的相对路径,多个文件夹以分号分隔。--> <probing privatePath="devLibs;3rdLibs;frameworkLibs"/> </assemblyBinding> </runtime> </configuration> ``` 其中privatePath是相对于*.exe.config文件的相对路径,多个文件夹以分号分隔。当编译后会在生成目录下生成一个后缀为.exe.config的文件,就是相对这个文件的。 添加程序集DLL引用之后,将DLL的属性“复制本地”设置为False。程序编译过程中,会自动检索Common和Security文件夹下的DLL及其依赖项。 我们框架就是使用这种方式来实现,最终的运行目录结构效果如下。 ![框架运行目录规划后的结构](http://doc.rdiframework.net/blog/article/20200418180317982.png-pw) ### 2.2.2、订阅程序集解析事件AssemblyResolve在代码中解析。 应用程序集域中支持在程序集解析时的处理: ```c# AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; ``` 通过这个事件,我们可以在程序集解析时,根据不同的程序集做不用的处理,比如加载x86的程序集还是64位的程序集,当然也就可以指定程序集目录了。这也正是`Assembly.Load`和`Assembly.LoadFrom`等方法的用武之地。 ```c# Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { AssemblyName assemblyName = new AssemblyName(args.Name); return Assembly.LoadFrom(Path.Combine(baseDirectory, "3rdLibs")); } ``` ### 2.2.3、在加载使用到dll的代码之前重置当前环境的目录。 这个方法是通过`Environment.CurrentDirectory=customPath`,这样在调用dll方法时,因为目录已经切换到了我们指定的目录下,就可以实现相应的dll正确的加载。这是一个**取巧**的方法不是很实用,需要来回切换程序集目录,但是在某些情况下非常好用。 ## 2.3、如何处理[dllImport]中的程序集的加载 针对dllImport也分为几种情况。 > 自己写`dllImport` > > 引用的C#的插件又使用了`dllImport` ### 2.3.1、自己写的dllImport 如果是自己写的就非常好控制了,可以直接指定相对的目录`DllImport(3rdLibs\NLog.dll)`。不过这种方法不一定可靠,在某些系统加载不了,如果使用了dllImport还是,推荐下面的介绍的方法(引用的C#的插件又使用了`dllImport`)。 ### 2.3.2、引用的C#的插件又使用了`dllImport` 因为无法更改路径,那么只能够使用上述特殊的方法,更改当前程序的路径 当然,还有更省事一点的做法,就是在系统环境中,增加一条记录,指向要加载的dll的所在目录。因为C++的代码中,Windows目录和Windows\System32目录以及环境变量设定的目录都是搜索路径之一。 这里提供怎么从C#中修改系统环境变量的代码: ```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); } ``` 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值。 # 3、运行效果 ![框架运行效果1](http://doc.rdiframework.net/blog/article/20200418180449429.png-pw) ![框架运行效果2](http://doc.rdiframework.net/blog/article/20200418180508962.png-pw) # 4、参考文章 ## 4.1、文章相关 - [用于运行时的程序集绑定元素](https://docs.microsoft.com/zh-cn/dotnet/framework/configure-apps/file-schema/runtime/assemblybinding-element-for-runtime?redirectedfrom=MSDN) - [浅谈.NET中程序集的动态加载](http://www.cnblogs.com/brucebi/archive/2013/05/22/Assembly_Load.html) - [注册使用GAC—Global Assembly Cache(.NET)](https://www.cnblogs.com/Ferry/archive/2010/12/17/1908817.html) - [再谈CLR查找和加载程序集的方式,查找程序集](http://www.cnblogs.com/chenxizhang/archive/2013/03/14/2959688.html) - [深入理解CLR类加载机制](http://www.cnblogs.com/baihmpgy/archive/2013/02/27/CLR_Loader_And_OSGi.html) - [C#程序集加载方法](https://blog.csdn.net/podded/article/details/3158687) ## 4.2、框架相关 [最好用的.NET敏捷开发框架-RDIFramework.NET V3.6版全新发布 100%源码授权](http://www.guosisoft.com/article/detail/237) [RDIFramework.NET — 基于.NET的快速信息化系统开发框架 — 系列目录](http://www.guosisoft.com/article/detail/190) [RDIFramework.NET敏捷开发框架 ━ 工作流程组件介绍](http://www.guosisoft.com/article/detail/233) [RDIFramework.NET框架SOA解决方案(集Windows服务、WinForm形式与IIS形式发布)-分布式应用](http://www.guosisoft.com/article/detail/189) [微信公众号开发系列-玩转微信开发-目录汇总](http://www.guosisoft.com/article/detail/216) [史上最全面的SignalR系列教程-目录汇总](http://www.guosisoft.com/article/detail/230) [RDIFramework.NET敏捷开发框架 ━ 工作流程组件Web业务平台](http://www.guosisoft.com/article/detail/234) [RDIFramework.NET敏捷开发框架通过SignalR技术整合即时通讯(IM)](http://www.guosisoft.com/article/detail/229) [RDIFramework.NET框架基于Quartz.Net实现任务调度详解及效果展示](http://www.guosisoft.com/article/detail/221) [RDIFramework框架整合微信开发应用效果展示](http://www.guosisoft.com/article/detail/219) ----- 一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,大家可以通过下面的地址了解详情。 RDIFramework.NET官方网站:http://www.rdiframework.net/ RDIFramework.NET官方博客:http://blog.rdiframework.net/ 同时需要说明的,以后的所有技术文章以官方网站为准,欢迎大家收藏! RDIFramework.NET框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用! 欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。 扫描二维码立即关注 ![微信号:guosisoft](http://doc.rdiframework.net/weixin.png)
正文到此结束
本文标签:
.NET
项目管理
挨踢业界
RDIF.NET
版权声明:
本站原创文章,由
guosisoft.com
发布,遵循
CC 4.0 by-sa
版权协议,转载请附上原文出处链接和本声明。
上一篇
微信公众号开发系列-玩转微信开发-目录汇总
下一篇
.NET快速开发框架-RDIFramework.NET 全新EasyUI版发布
热门推荐
{{article.title}}
热门指数:
浏览({{article.lookCount + 5000}})
相关文章
{{article.title}}
该篇文章的评论功能暂时被站长关闭
说给你听
本文目录
文章标签
RDIF.NET
其他
微信开发
.NET
消息交互
.NetCore
项目管理
常用工具
工作流
Web前端
数据库
挨踢业界
随机文章
.NET快速信息化系统开发框架 V3.2-模块管理按子系统进行分类管理
微信公众号开发系列-玩转微信开发-目录汇总
ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)
RDIFramework.NET敏捷开发框架 ━ 工作流程组件Web业务平台
《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航
国思RDIF.vNext全新低代码快速开发框架平台6.1版本发布(支持vue2、vue3)
玩转数据库索引
RDIFramework.NET V3.2-> “Tab”标签新增可“最大化”显示功能
如何有效创建工作分解结构?
后台界面设计之表格设计规范参考
.NET快速信息化系统开发框架 V3.2->Web版本模块管理界面新增模块排序功能
[推荐]ORACLE SQL:经典查询练手第一篇(不懂装懂,永世饭桶!)
RDIFramework.NET敏捷开发框架WinForm新增通用附件管理控件
微信公众号开发C#系列-6、消息管理-普通消息接受处理
常用linux命令,开发必备
团队项目开发"编码规范"之六:语句
.NET快速信息化系统开发框架 V3.2->新增“行政区域管理”,同时大批量树采用异步加载
信息系统项目管理系列之四:项目可行性研究与评估
ORACLE PL/SQL编程之八:把触发器说透
RDIFramework.NET平台代码生成器V3.1.6125.27586全新发布-更新于20161029(提供下载)
网站信息
文章总数:599 篇
标签总数:8 个
分类总数:8 个
留言数量:1385 条
在线人数:
89
人
运行天数:1321天
最后更新:2023-05-18
QQ:406590790
13005007127