Search code examples
c#reference.net-assemblyroslyn

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


According to this post: Is there a way to setup a working directory for "r and "load commands

The #r directive can be use with relative path, but it's an old post and I failed finding any relevant recent documentation about that specifically (searched whole afternoon yesterday)

I'm able to add the reference of an assembly of mine when I provide the full absolute path, but it does not work with relative path.

The dll is in the current directory of the running script (verified through Environment.CurrentDirectory from the running script):

I tried all those forms:

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

Only the last one was working.

I'm using Roslyn library retrieved from NuGet:

Microsoft.CodeAnalysis.CSharp.Scripting

Version 3.1.0

Has the support for relative path been removed?


Solution

  • From where is the script runner of the script executing?


    If you are using csi.exe via the command-line, for example:

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

    Environment.CurrentDirectory will be the current directory of where csi.exe was launched (i.e. c:\dir1) and not of the script file (i.e. c:\dir1\path\to\script).


    If you are using Visual Studio C# Interactive window to #load the file then it is c:\Users\<your user name> and not the filepath of the script.


    If you are using a custom application referencing Microsoft.CodeAnalysis.CSharp.Scripting library then Environment.CurrentDirectory will be the file location of your custom app and not of the script.

    A way to resolve this is to set Environment.CurrentDirectory to be same as the file directory of your script file (which I'd assume your custom app code would know if it's loading the file somehow) before CSharpScript.EvaluateAsync() is called.

    For example in your custom app you can do the following:

    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);
    

    Unfortunately, after testing for myself even after changing Environment.CurrentDirectory as suggested in Is there a way to setup a working directory for “r and ”load commands #r still does not work when using relative path. If that did once work then yes it looks to be regression since when that answer was originally posted.