Директива #r в скрипте C# не поддерживает относительные пути

Согласно этому сообщению: Есть ли способ настроить рабочий каталог для команд «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

Была ли удалена поддержка относительного пути?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 745
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Откуда выполняется скрипт-раннер скрипта?


Если вы используете 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, все еще не работает при использовании относительного пути. Если это когда-то сработало, то да, похоже, это регрессия с тех пор, как этот ответ был первоначально опубликован.

Я использую код С#. Из нашего собственного приложения, которое поддерживает настройку с помощью файла .csx. Я использую библиотеку из NuGet Microsoft.CodeAnalysis.CSharp.Scripting в этом приложении и запускаю скрипт, используя библиотечный метод: CSharpScript.EvaluateAsync(). Я сделал Environment.CurrentDirectory из скрипта, поэтому в «области действия» скрипта , каталог правильный с точки зрения скрипта. (То же самое, где находится dll, на который я хочу сослаться).

Francis P 12.06.2019 22:00

@ФрэнсисП Хорошо. Спасибо за разъяснения. Как и в моем первоначальном ответе, похоже, что Environment.CurrentDirectory работает из контекста вашего пользовательского приложения, ссылающегося на библиотеку Microsoft.CodeAnalysis.CSharp.Scripting. В частности, путь к файлу, в котором находится и запускается ваше приложение, а не место, где находится скрипт. Смотрите мой обновленный ответ для возможного исправления.

Ray 13.06.2019 00:11

Хорошо. Только что проверил и подтвердил, что #r с относительным путем не работает, несмотря на изменение Environment.CurrentDirectory перед выполнением скрипта. :(

Ray 13.06.2019 07:52

Я тоже столкнулся с этой проблемой и после некоторого копания нашел решение для себя на 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

Другие вопросы по теме