在 dotnet 有很多方法可以获取当前程序所在的路径,但是这些方法获取到的路径有一点不相同,特别是在工作路径不是当前的程序所在的路径的时候



通过下面几个方法都可以拿到程序所在的文件夹或程序文件

  • AppDomain.CurrentDomain.BaseDirectory 当前程序域寻找 dll 的文件夹
  • Environment.CurrentDirectory 当前工作文件夹
  • Assembly.GetCallingAssembly().Location 调用当前函数的函数的程序集的文件
  • Assembly.GetEntryAssembly().Location 入口函数程序集所在的文件
  • Assembly.GetExecutingAssembly().Location 包含当前代码的程序集的文件
  • Directory.GetCurrentDirectory 当前工作文件夹

如写一个 SetereBojerhis 控制台程序,将这个程序放在 D:\lindexi\dotnet 获取程序所在路径的方法\ 然后双击运行这个程序,可以看到下面代码

AppDomain.CurrentDomain.BaseDirectory=D:\lindexi\dotnet 获取程序所在路径的方法\
Environment.CurrentDirectory=D:\lindexi\dotnet 获取程序所在路径的方法
Assembly.GetCallingAssembly().Location=D:\lindexi\dotnet 获取程序所在路径的方法\SetereBojerhis.exe
Assembly.GetEntryAssembly().Location=D:\lindexi\dotnet 获取程序所在路径的方法\SetereBojerhis.exe
Assembly.GetExecutingAssembly().Location=D:\lindexi\dotnet 获取程序所在路径的方法\SetereBojerhis.exe
Directory.GetCurrentDirectory()=D:\lindexi\dotnet 获取程序所在路径的方法
AppDomain.CurrentDomain.SetupInformation.ApplicationBase=D:\lindexi\dotnet 获取程序所在路径的方法\
Process.GetCurrentProcess().MainModule.FileName=D:\lindexi\dotnet 获取程序所在路径的方法\SetereBojerhis.exe

虽然看起来大多数的值都是相同的,但是还是有很多区别

Assembly.GetCallingAssembly

获取调用这个函数的函数,如 Foo 函数里面调用了 Assembly.GetCallingAssembly 方法,那么将会返回调用 Foo 函数的函数所在程序集的文件路径

如存在程序集 A1 里面的 M1 方法,在 M1 方法调用 Assembly.GetCallingAssembly 方法。此时在程序集 A2 的 M2 方法调用了 M1 那么将会返回 M2 方法所在的程序集 A2 的文件

但是还有一个要求是 M1 方法不是内联到 M2 方法里面,如果进行内联,那么会让实际的 IL 在 M2 里面,也就是相当于是 M2 方法里面调用 Assembly.GetCallingAssembly 方法,不让一个方法作为内联可以使用 MethodImplOptions 特性

  [MethodImpl (MethodImplOptions.NoInlining)]
public static void OtherMethod ()
{
//这个方法将不会被内联
}

Assembly.GetEntryAssembly

获取入口程序集,一般的入口程序集就是包含 Main 函数的程序集,一个程序里面是可以存在多个 Main 函数,具体调用哪个可以在编译的时候指定,详细请看 .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换 - walterlv

通过在任意代码调用 Assembly.GetEntryAssembly 可以拿到当前调用的入口函数所在的程序集

但是这个方法相对使用的性能比较多,如果在调用 Assembly.GetEntryAssembly 方法所在的程序集和入口函数在不同程序集,那么性能将会比较差

同时如果是由非托管调用的函数,也就是入口函数不是托管代码那么调用 Assembly.GetEntryAssembly 将会返回空

Assembly.GetExecutingAssembly

获取当前运行代码的程序集,如我在 Foo 方法调用 Assembly.GetExecutingAssembly 那么将会返回调用的代码所在的程序集

   static void Foo()
{
// Get the currently executing assembly.
Assembly currentAssembly = Assembly.GetExecutingAssembly();
Console.WriteLine("Currently executing assembly:");
Console.WriteLine(" {0}\n", currentAssembly.FullName); }

性能

已经几个获取方法的性能对比

Method Mean Error StdDev Median
AppDomainCurrentDomainBaseDirectory 781.5 ns 19.489 ns 23.200 ns 781.4 ns
EnvironmentCurrentDirectory 497.8 ns 10.076 ns 25.464 ns 486.2 ns
AssemblyGetCallingAssemblyLocation 3,550.6 ns 20.228 ns 17.932 ns 3,555.4 ns
AssemblyGetEntryAssemblyLocation 2,783.2 ns 33.407 ns 31.249 ns 2,791.1 ns
AssemblyGetExecutingAssemblyLocation 3,021.7 ns 32.517 ns 30.416 ns 3,018.8 ns
DirectoryGetCurrentDirectory 472.2 ns 3.871 ns 3.621 ns 471.4 ns

AppDomain.CurrentDomain.SetupInformation

关于 AppDomain.CurrentDomain.SetupInformation 和 Process.GetCurrentProcess().MainModule.FileName 的方法请看

三种方法获取可执行程序的文件路径(.NET Core / .NET Framework) - walterlv

参考文档

Assembly.GetEntryAssembly Method (System.Reflection)

Assembly.GetExecutingAssembly Method (System.Reflection)

Assembly.GetCallingAssembly Method (System.Reflection)

三种方法获取可执行程序的文件路径(.NET Core / .NET Framework) - walterlv

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

dotnet 获取程序所在路径的方法的更多相关文章

  1. 2019-8-31-dotnet-获取程序所在路径的方法

    title author date CreateTime categories dotnet 获取程序所在路径的方法 lindexi 2019-08-31 16:55:58 +0800 2019-03 ...

  2. Qt 程序获取程序所在路径、用户目录路径、临时文件夹等特殊路径的方法

    Qt 程序获取程序所在路径.用户目录路径.临时文件夹等特殊路径的方法 经常我们的程序中需要访问一些特殊的路径,比如程序所在的路径.用户目录路径.临时文件夹等.在 Qt 中实现这几个功能所用的方法虽然都 ...

  3. delphi根据进程PID获取程序所在路径的函数(用OpenProcess取得句柄,用GetModuleFileNameEx取得程序名)

    uses psapi; {根据进程PID获取程序所在路径的函数}function GetProcessExePath(PID: Cardinal): string;varpHandle: THandl ...

  4. C# WinForm获取程序所在路径方法

    多个获取WinForm程序所在文件夹路径的方法,收藏备忘. 1)获取当前进程的完整路径,包含文件名(进程名). 代码:string str =this.GetType().Assembly.Locat ...

  5. 【转】MFC获取程序目录路径方法

    原文网址:http://yeahyuanqing.blog.163.com/blog/static/118025091201149480818/ MFC获得当前应用程序目录的GetCurrentDir ...

  6. Delphi获取文件名、文件名不带扩展名、文件名的方法;delphi 获取文件所在路径

    取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一:   Function Extrac ...

  7. 【转】 C#获取当前程序运行路径的方法集合

    [转] C#获取当前程序运行路径的方法集合 //获取当前进程的完整路径,包含文件名(进程名). string str = this.GetType().Assembly.Location; resul ...

  8. Delphi XE的firemonkey获取当前文件所在路径的方法

    Delphi XE的firemonkey获取当前文件所在路径的方法 在之前,我们知道有三种方法: ExtractFilePath(ParamStr(0)) ExtractFilePath(Applic ...

  9. C#、ASP.NET获取当前应用程序的绝对路径,获取程序工作路径 (转帖)

    C#.ASP.NET获取当前应用程序的绝对路径,获取程序工作路径   ============================================ 使用 Application.Start ...

随机推荐

  1. JavaScript--时间日期格式化封装

    这是一个正常的封装: 其他非正常的请按照以下语句自由搭配 <!DOCTYPE html> <html lang="en"> <head> < ...

  2. 【JZOJ4868】【NOIP2016提高A组集训第9场11.7】Simple

    题目描述 数据范围 解法 在暴力枚举的基础上,当n的系数在[0,m/gcd(n,m))时,得到的c是不重复不遗漏的. 设n的系数为x,m的系数为y. 不重复不遗漏性 设x=m/gcd(n,m)+i,那 ...

  3. ANSI编码方式转化为UTF-8方式

    说明: 记事本txt有四种编码方式,分别为:UTF-8.ANSI.Unicode和Unicode big endian,当进行写操作,创建的txt编码格式,与写入汉字的编码方式相同:如果写入的汉字是不 ...

  4. thinkphp5.0 模板包含文件

    在index.html里包含layout.html:{include file=“layout”}它这里是以绝对路径查找所包含的文件,默认是view目录下 在这种情况下,要在在index.html里包 ...

  5. CSS3摆动动画效果

    效果图:红包在左右摇晃 代码如下: @keyframes upAnimation { 0 % { transform: rotate(0 deg);transition - timing - func ...

  6. 蓝牙(3)蓝牙UUID与SDP

    1.服务发现协议 (SDP) SDP = Service Discovery Protocol  主要用来根据已分配编号(UUID)搜索服务.浏览群组列表.文档 URL 和图标 URL等. 详细见: ...

  7. CSS文本超过两行用省略号代替

    1.只显示一行,超出部分用省略号 white-space: nowrap; overflow: hidden; text-overflow: ellipsis; 2.只显示两行(或多行),超出部分用省 ...

  8. Mysql 数据库优化(一)

    一 避免网页访问错误 1  数据库连接timeout产生页面5xx错误 2 慢查询造成页面无法加载 3 阻塞造成数据无法提交 二 增加数据库的稳定性 三 优化用户体验 1 流畅的页面访问速度 2 良好 ...

  9. OpenResty,X-WAF防火墙相关

    >>OpenResty<< >>Lua教程<< >>反向代理百度百科<< >>X-WAF配置指南<<

  10. django 中models表的多对一,多对多的理解

    django 表的理解 好处:设计的好,会清晰,易于理解和维护,后期开发事半功倍,一目了然. 1. 一对一的表,两表的属性实际上完全可以合并成一个表,共用一个主键即可: 2. 一对多的表,可以设中间关 ...