在大部分情况下,获取当前所运行的应用程序的所在路径时,常用的就是 Assembly.Location 属性,按照之前的经验,使用 Assembly.Location 是最为稳定的做法,然而在 dotnet 发布单文件时,此属性将会为空,导致一些不符合预期的行为

通过 Assembly.Location 属性可以返回程序集所在的文件路径,这个一个比较稳定的获取某个路径方式,至少比获取当前的工作路径 Environment.CurrentDirectoryDirectory.GetCurrentDirectory() 都要稳定得多。每次使用 Assembly.Location 都是返回程序集所在的文件路径,而工作路径 Environment.CurrentDirectoryDirectory.GetCurrentDirectory() 则是返回当前的工作路径,而大家都知道,工作路径是可以非常简单的被进行更改的,从而导致每次调用 Environment.CurrentDirectoryDirectory.GetCurrentDirectory() 都可以返回不同的值。当然了,是否使用工作路径,这也是看大家的需求的

如果大家在阅读以上内容时,还没有工作路径的概念,还请先自行了解一下工作路径是什么以及工作路径的用途是什么

在单文件发布这个功能之前,当咱需要获取当前的应用程序安装路径,在不考虑插件 DLL 存在的情况下,我是推荐使用 Assembly.Location 属性获取当前的应用程序所在的文件夹的,大概的代码如下

string installFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;

这里无论是采用 GetExecutingAssembly 也好,还是 GetEntryAssembly 方法都对于应用程序来说是正确的。但是由于单元测试下是没有入口的程序集的也就是 GetEntryAssembly 将返回空,于是此时换成 GetExecutingAssembly 获取当前正在运行的代码所在的程序集将是更加稳定的

通过以上方式获取应用程序路径将比使用 AppDomainSetup.ApplicationBase 更加稳定,如以下代码是通过 AppDomainSetup.ApplicationBase 获取路径

// 以下代码是不推荐的
string? installFolder = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

然而原本比较稳定的 Assembly.Location 属性将在进行单文件发布时,返回空字符串。这就让许多现有的逻辑不能正常工作,好在发布单文件时,将会看到 VisualStudio 的以下提示内容

IL3000: Avoid accessing Assembly file path when publishing as a single file

这时候的推荐使用的是 AppContext.BaseDirectory 属性,这个属性也是用来返回当前应用程序的安装路径的稳定属性

换句话说就是在使用 dotnet core 时,无论是 .NET Core 3.1 还是 dotnet 6 版本,在获取当前应用程序的安装路径时,都可以使用 AppContext.BaseDirectory 属性。使用这个属性不仅代码短,且稳定

那此时就有伙伴会疑惑,为什么我之前推荐都是使用 Assembly.Location 属性。这是因为我的许多基础库和项目那会都需要兼容 .NET Framework 4.5 版本,而 AppContext.BaseDirectory 是在 .NET Framework 4.6 之后才引入的,这就是为什么我没有推荐过这个属性的原因

如果自己的项目里面有大量的旧代码都是采用 Assembly.Location 属性,感觉改不动,或者是在基础库里面就是采用 Assembly.Location 属性的,那可以使用配置方式切换为兼容逻辑,如下面代码

AppContext.SetSwitch("Switch.System.Reflection.Assembly.SimulatedLocationInBaseDirectory", true);

以上配置推荐加在 Main 函数第一句话里面,加上以上配置之后,即可让 Assembly.Location 属性返回的是当前单文件的路径,而不会返回空字符串

以上的配置内容是在 https://github.com/dotnet/corert/issues/5467 里面大佬提供的

更多博客内容请参阅我的 博客导航博客园的合集

dotnet 警惕 Assembly.Location 返回空的更多相关文章

  1. ubuntu下file_get_contents返回空字符串

    ubuntu下file_get_contents返回空字符串 | 浏览:302 | 更新:2014-03-30 10:11 本文起初面临的问题是PHP中SoapClient不好使,最后file_get ...

  2. win10 uwp 解决 SerialDevice.FromIdAsync 返回空

    调用 SerialDevice.FromIdAsync 可能返回空,因为没有设置 package.appmanifest 可以使用端口 打开 package.appmanifest 文件添加下面代码 ...

  3. Handler 接收Parcelable ArrayList时返回空的错误

    遇到一个问题,从handler 接收的Parcelable ArrayList返回空,调试发现这个arraylist生成的时候是有值的,传到handler就没值了 赋值的代码 new Thread(n ...

  4. 返回空的list集合*彻底删除删除集合*只是清空集合

    ---------- 要求返回空的List集合----------- List<String> allList = Collections.emptyList();// 返回空的List集 ...

  5. Effective Java 第三版——54. 返回空的数组或集合不要返回null

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  6. shell脚本中sqlite3命令查询数据库失败返回空,并将错误信息打印到标准错误输出

    shell脚本中sqlite3命令查询数据库失败返回空,并将错误信息打印到标准错误输出 如: #/bin/sh local ret='sqlite3 test.db "select test ...

  7. jenkins坑—— shell 命令返回空导致构建失败

    今天用jenkins做CI遇到个坑,命令为:isSnapshot=`ls|grep isv-osp-service|grep -i snapshot` ls命令返回空的话,Jenkins构建就直接失败 ...

  8. python3中使用xpath无法定位,为什么一直返回空列表?

    tbody问题: 在爬去某些网站一些信息的时候,xpath工具上显示类容是正确的,但是在scrapy代码中一直返回空列表 Scrapy的部分代码: class LotteryspiderSpider( ...

  9. laravel使用Dingo\Api通过response()->json()返回空对象

    laravel使用Dingo\Api写接口跟android对接时,android一直反应解析错误,无法解析数据. { "status_code":200, "messag ...

  10. iOS获取iPhone系统等信息和服务器返回空的异常处理

    前言: 在项目中经常会遇到需要获取系统的信息来处理一些特殊的需求和服务端返回为空的处理,写在这里只是笔记一下. 获取设备的信息 NSLog(@"globallyUniqueString=%@ ...

随机推荐

  1. Bootstrap前端开发框架

    一 Bootstrap 简介 Bootstrap 来自 Twitter(推特),是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS 和 JAVASCRIPT 的,它简洁灵活,使得 ...

  2. 崩溃bug日志总结2

    目录介绍 1.1 java.lang.ClassNotFoundException类找不到异常 1.2 java.util.concurrent.TimeoutException连接超时崩溃 1.3 ...

  3. 记录转载:uni-app 请求 uni.request封装使用

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 对uni.request的一些共同参数进行简单的封装,减少重复性数据请求代码.方便全局调用. 先在目录下创建 utils 和 common ...

  4. 如何在uniapp中优雅地使用WebView

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 从webview页面传值到uniapp中 官方文档已经很详细了,这里给大家上我的实战代码,首先在webview页面中引入相关依赖: < ...

  5. FFmpeg开发笔记(六)如何访问Github下载FFmpeg源码

    ​学习FFmpeg的时候,经常要到GitHub下载各种开源代码,比如FFmpeg的源码页面位于https://github.com/FFmpeg/FFmpeg.然而国内访问GitHub很不稳定,经常打 ...

  6. Scala数值类型转换、算数运算符、关系(比较)运算符和逻辑运算符

    原则 强制类型转换 Java : int num = (int)2.5Scala : var num : Int = 2.7.toInt 数值类型和String类型之间的转换 (1)基本类型转 Str ...

  7. Jetpack Compose(4)——重组

    目录 一.状态变化 1.1 状态变化是什么 1.2 mutableStateListOf 和 mutableStateMapOf 二.重组的特性 2.1 Composable 重组是智能的 2.2 C ...

  8. #排列组合#CF1550D Excellent Arrays

    洛谷传送门 CF1550D 分析 对于excellent的 \(a\) 来说 \(|a_i-i|=x\) 的值是固定的,考虑枚举它 一半正一半负时函数值是最大的,当 \(n\) 为奇数时要分为两种情况 ...

  9. #线段树,组合计数,二项式定理#CF266E More Queries to Array

    洛谷传送门 CF266E传送门 分析 首先区间修改区间查询首选线段树 要找突破口,\((i-l+1)^k\)中\(i\)不是定值, 显然得拆开,而且\(k\)很小,根据二项式定理, \[\sum_{i ...

  10. #完全背包输出具体方案#AT4298 [ABC118D] Match Matching

    题目 分析 首先,用完全背包求出\(n\)根火柴能够组成的最大位数, 然后选择尽量大的数字拼凑即可 代码 #include <cstdio> #include <cctype> ...