电脑桌面
添加蚂蚁七词文库到电脑桌面
安装后可以在桌面快捷访问

.NET 程序读取当前目录避坑指南

来源:金蝶云社区作者:金蝶2024-09-163

.NET 程序读取当前目录避坑指南

.NET 程序读取当前目录避坑指南

前些天有 AgileConfig 的用户反映,如果把 AgileConfig 部署成 Windows 服务程序会启动失败。我看了一下日志,发现根目录被定位到了 C:\Windows\System32 下,那么读取 appsettings.json 配置文件自然就失败了。

 var builder = new ConfigurationBuilder()
                   .SetBasePath(Directory.GetCurrentDirectory());

以上是我构造 ConfigurationBuilder 的代码。使用 Directory.GetCurrentDirectory() 获取程序根目录然后设置 SetBasePath 。以上代码在99%的情况是不会有问题的,那么为什么会在做为服务部署的时候会有问题呢?让我们往下看。

Directory.GetCurrentDirectory()

Directory.GetCurrentDirectory() 获取根目录是我们很常见的一个操作。先让我们对其进行一些简单的测试。新建一个控制台程序,编写以下代码进行:

var dirpath = Directory.GetCurrentDirectory();Console.WriteLine("Directory.GetCurrentDirectory = " + dirpath);

直接运行

代码很简单,就是读取根目录,然后输出一下。

Directory.GetCurrentDirectory = C:\00WORKSPACE\basedir\basedir\bin\Debug\net6.0

编译完成后双击 exe 文件,可以看到获取到的目录是正确的。

使用 cmd 运行

下面让我们试一下在 cmd 下运行这个 exe 。

C:\>cd C:\00WORKSPACE\basedir\basedir\bin\Debug\net6.0C:\00WORKSPACE\basedir\basedir\bin\Debug\net6.0>basedir.exeDirectory.GetCurrentDirectory = C:\00WORKSPACE\basedir\basedir\bin\Debug\net6.0

我们把路径切换到 exe 所在的目录,然后输入 basedir.exe 直接运行它,可以看到输出的目录也是正确的。

切换工作目录

这次我们把工作目录切换到 C 盘的 apps 目录,然后使用完全路径去执行 exe 程序。

C:\>cd appsC:\APPS>C:\00WORKSPACE\basedir\basedir\bin\Debug\net6.0\basedir.exeDirectory.GetCurrentDirectory = C:\APPS

怎么样?是不是跟预期的不一样了?这次输出的根目录不是 exe 所在的目录,而是 c:\APPS ,也就是我们的工作目录。

使用另外一个 exe 程序启动测试程序

在我们日常场景中有很多时候需要通过一个程序去运行另外一个程序,那么这个时候 Directory.GetCurrentDirectory 获取的根目录是怎么样的呢?
首先我们编写另外一个 WPF 的程序,使用这个程序来启动我们的 basedir.exe 测试程序。
我们把这个 WPF 程序放在 c:\APPS 目录下,然后运行它:

其中按钮的事件代码如下:

private void Button_Click(object sender, RoutedEventArgs e)
        {            var process = new Process();
            process.StartInfo.FileName = this.path.Text;
            process.Start();
        }

点击这个按钮,它会把我们的测试程序 basedir.exe 给运行起来:

我们可以看到,当 WPF 程序把我们的测试程序运行起来的时候,测试程序输出的目录为 c:\APPS,也就是 WPF 程序所在的目录。

为什么做为服务运行的时候获取程序根目录为 System32

通过以上的测试,AgileConfig 做为服务运行的时候获取根目录为 C:\Windows\System32 的原因已经很明显了。我们的 windows 服务的启动一般来说有2个途径,一个是通过 sc.exe 工具另外一个是通过 services.exe 也就是 SCM (service control manager) 来启动。那么这2个可执行程序在哪里呢?答案就是 C:\Windows\System32 。我们的 windows 服务的启动其实是通过这2个工具来运行的,所以根据上面的测试,很明显通过Directory.GetCurrentDirectory来获取根目录的话会是这2个工具所在的目录。

其它读取程序根目录的方式

通过以上我们知道通过Directory.GetCurrentDirectory读取根目录会有一点小坑。在我们的 .NET 世界里还有很多办法能获取根目录,那么他们会不会也有坑呢?
以下列几个常见的获取根目录的方法:

var dirpath = Directory.GetCurrentDirectory();
Console.WriteLine("Directory.GetCurrentDirectory = " + dirpath);// 通过 AppDomain.CurrentDomain.BaseDirectory 读取根目录var dirpath1 = AppDomain.CurrentDomain.BaseDirectory;
Console.WriteLine("AppDomain.CurrentDomain.BaseDirectory = " + dirpath1);// 通过 Environment.CurrentDirectory 来读取根目录var dirpath2 = Environment.CurrentDirectory;
Console.WriteLine("Environment.CurrentDirectory = " + dirpath2);// 通过 Assembly.GetExecutingAssembly().Location 来获取运行程序集所在的位置,从而判断根目录var dirpath3 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Console.WriteLine("Path.GetDirectoryName Assembly.GetExecutingAssembly().Location = " + dirpath3);// 通过 AppContext.BaseDirectory 获取根目录var dirpath4 = AppContext.BaseDirectory;
Console.WriteLine("AppContext.BaseDirectory = " + dirpath4);

直接运行

把以上获取根目录的代码补充进我们的测试程序,编译成功后直接运行:

Directory.GetCurrentDirectory = C:\00WORKSPACE\basedir\basedir\bin\Debug\net6.0AppDomain.CurrentDomain.BaseDirecto

.NET 程序读取当前目录避坑指南

.NET 程序读取当前目录避坑指南前些天有 AgileConfig 的用户反映,如果把 AgileConfig 部署成 Windows 服务程序会启动失败。我看了...
点击下载文档文档为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

已经是第一篇
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息
QQ群
  • 答案:my7c点击这里加入QQ群
支持邮箱
微信
  • 微信