Search code examples
.netnode.jsvisual-studio-2015c++-cli

Assembly::GetExecutingAssembly()->Location now throws ArgumentException: Illegal characters in path


In a node.js native addon in Visual Studio 2010 (and .Net 4) I could use

System::Reflection::Assembly::GetExecutingAssembly()->Location

to get the path of the running C++/CLI assembly, but in a node.js addon in Visual Studio 2015 project (and .Net 4.6), I get an exception:

System.ArgumentException: Illegal characters in path.
   at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
   at System.Security.Permissions.FileIOPermission.CheckIllegalCharacters(
      String[] str)
   at System.Security.Permissions.FileIOPermission.AddPathList(
      FileIOPermissionAccess access, AccessControlActions control,
      String[] pathListOrig, Boolean checkForDuplicates,
      Boolean needFullPath, Boolean copyPathList)
   at System.Security.Permissions.FileIOPermission..ctor(
      FileIOPermissionAccess access, String path)
   at System.Reflection.RuntimeAssembly.get_Location()

Any idea how to get the path of the running assembly?

Edit 2018-01-25 This is still not resolved with Visual Studio 2017, this time trying .Net 4.5.2


Solution

  • Although the Location property throws, CodeBase can still be used, which returns something like:

    file://?/C:/.../my-addon.node
    

    And that would explain the illegal character: The '?'

    A new Uri(Application.CodeBase).LocalPath will return

    /?/C:/.../my-addon.node
    

    so a workaround for GetExecutingAssembly()->Location could be:

    String^ GetExecutingAssemblyLocation()
    {
      try
      {
        return Path::GetDirectoryName(Assembly::GetExecutingAssembly()->Location);
      }
      catch (Exception^ e)
      {
        String^ codeBase = Assembly::GetExecutingAssembly()->CodeBase;
        if (codeBase->StartsWith("file://?/"))
        {
          Uri^ codeBaseUri = gcnew Uri("file://" + codeBase->Substring(8));
          return codeBaseUri->LocalPath;
        }
        else
          throw;
      }
    }
    

    which will return

    C:\...\my-addon.node