Согласно этому сообщению: Есть ли способ настроить рабочий каталог для команд «r» и «load».
Директиву #r
можно использовать с относительным путем, но это старый пост, и мне не удалось найти какую-либо актуальную недавнюю документацию об этом конкретно (искал вчера весь день)
Я могу добавить ссылку на свою сборку, указав полный абсолютный путь, но это не работает с относительным путем.
DLL находится в текущем каталоге запущенного скрипта (проверено через Environment.CurrentDirectory
из запущенного скрипта):
Я пробовал все эти формы:
#r ".\MyLib.dll"
#r "MyLib.dll"
#r "D:\Absolute\Path\To\MyLib.dll"
Работал только последний.
Я использую библиотеку Roslyn, полученную из NuGet:
Microsoft.CodeAnalysis.CSharp.Scripting
Версия 3.1.0
Была ли удалена поддержка относительного пути?
Откуда выполняется скрипт-раннер скрипта?
Если вы используете 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# для #load
файла, то это c:\Users\<your user name>
, а не путь к файлу скрипта.
Если вы используете пользовательское приложение, ссылающееся на Microsoft.CodeAnalysis.CSharp.Scripting
библиотеку, то Environment.CurrentDirectory
будет расположением файла ваше пользовательское приложение, а не скрипта.
Способ решить эту проблему состоит в том, чтобы установить Environment.CurrentDirectory
таким же, как каталог файла вашего файла сценария (который, как я полагаю, ваш пользовательский код приложения будет знать, если он каким-то образом загружает файл) до вызова 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);
К сожалению, после проверки на себе, даже после изменения Environment.CurrentDirectory
, как было предложено в Есть ли способ настроить рабочий каталог для команд «r» и «load»?#r
, все еще не работает при использовании относительного пути. Если это когда-то сработало, то да, похоже, это регрессия с тех пор, как этот ответ был первоначально опубликован.
@ФрэнсисП Хорошо. Спасибо за разъяснения. Как и в моем первоначальном ответе, похоже, что Environment.CurrentDirectory
работает из контекста вашего пользовательского приложения, ссылающегося на библиотеку Microsoft.CodeAnalysis.CSharp.Scripting
. В частности, путь к файлу, в котором находится и запускается ваше приложение, а не место, где находится скрипт. Смотрите мой обновленный ответ для возможного исправления.
Хорошо. Только что проверил и подтвердил, что #r
с относительным путем не работает, несмотря на изменение Environment.CurrentDirectory
перед выполнением скрипта. :(
Я тоже столкнулся с этой проблемой и после некоторого копания нашел решение для себя на github. Я не могу найти ссылку прямо сейчас, но я обновлю, если найду ее снова.
Согласно ответу на вопрос на 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);
Это решило проблему для меня, и теперь относительные пути разрешаются относительно пути к файлу сценария.
Обновлять: ссылка на выпуск на github https://github.com/dotnet/roslyn/issues/36417
Я использую код С#. Из нашего собственного приложения, которое поддерживает настройку с помощью файла .csx. Я использую библиотеку из NuGet Microsoft.CodeAnalysis.CSharp.Scripting в этом приложении и запускаю скрипт, используя библиотечный метод: CSharpScript.EvaluateAsync(). Я сделал Environment.CurrentDirectory из скрипта, поэтому в «области действия» скрипта , каталог правильный с точки зрения скрипта. (То же самое, где находится dll, на который я хочу сослаться).