C# 脚本中的#r 指令不支持相对路径

The #r directive in C# script does not support relative paths

根据这个post: Is there a way to setup a working directory for "r and "load commands

#r 指令可以与相对路径一起使用,但它是一个旧的 post,我没有找到任何相关的最新文档(昨天搜索了整个下午)

当我提供完整的绝对路径时,我可以添加我的程序集的引用,但它不适用于相对路径。

dll在运行脚本的当前目录中(通过运行脚本的Environment.CurrentDirectory验证):

我尝试了所有这些形式:

#r ".\MyLib.dll"
#r "MyLib.dll"
#r "D:\Absolute\Path\To\MyLib.dll"

只有最后一个有效。

我正在使用从 NuGet 检索到的 Roslyn 库:

Microsoft.CodeAnalysis.CSharp.Scripting

版本 3.1.0

是否移除了对相对路径的支持?

脚本的脚本运行器从哪里执行?


如果您通过 command-line 使用 csi.exe,例如:

C:\dir1>csi.exe .\path\to\script\myScript.csx 

Environment.CurrentDirectory 将是启动 csi.exe 的当前目录(即 c:\dir1),而不是脚本文件(即 c:\dir1\path\to\script)。


如果您使用 Visual Studio C# Interactive window#load 文件,那么它是 c:\Users\<your user name> 而不是脚本的文件路径。


如果您使用的是 自定义应用程序引用 Microsoft.CodeAnalysis.CSharp.Scripting,那么 Environment.CurrentDirectory 将是 您的自定义应用程序[的文件位置] =50=] 而不是脚本。

解决这个问题的一种方法是在CSharpScript.EvaluateAsync() 被调用。

例如,在您的自定义应用程序中,您可以执行以下操作:

using Microsoft.CodeAnalysis.CSharp.Scripting;
// ...

            var scriptDirectory = @"c:\dir1\path\to\script"; // <-- or however else you are getting this. will use this later
            var scriptFilename = "myScript.csx";
            var scriptFilepath = Path.Combine(scriptDirectory, scriptFilename);

            var scriptCode = File.ReadAllText(scriptFilepath);

            Environment.CurrentDirectory = scriptDirectory; // <-- set this before running the script below

            var result = await CSharpScript.EvaluateAsync(scriptCode);

不幸的是,即使按照 Is there a way to setup a working directory for “r and ”load commands 中的建议更改 Environment.CurrentDirectory 后,我自己进行了测试,但在使用相对路径时 #r 仍然不起作用。如果那确实曾经奏效,那么是的,自最初发布该答案以来,它看起来是倒退。

我也遇到了这个问题,经过一番挖掘,我在 github 上找到了适合我的解决方案。我现在找不到 link,但如果我再次找到它,我会更新。

根据github上问题的回答,相对路径只有在直接执行脚本文件时才有效。 Roslyn 不再使用 Environment.CurrentDirectory 来搜索库。问题是,当使用 CSharpScript.EvaluateAsync 时,您不是 运行 脚本文件,而是在评估字符串,因此 roslyn 甚至不会尝试解析任何相对路径。

解决方案是在 ScriptOptions 中提供文件路径:

var scriptCode = File.ReadAllText(scriptFilepath);

var opt = ScriptOptions.Default
            .WithFilePath(scriptFilePath);

var result = await CSharpScript.EvaluateAsync(scriptCode, options: opt);

这解决了我的问题,现在相对路径是相对于脚本文件的路径来解决的。

更新: link 发布于 github https://github.com/dotnet/roslyn/issues/36417