Question

I have a very simple class CompiledFunction (MarshalByRefObject) - I try to create an instance of this in a new domain like so

var appDomainSetup = new AppDomainSetup();
appDomainSetup.ApplicationBase = Path.GetDirectoryName(typeof(CompilerService).Assembly.CodeBase);
var evidence = AppDomain.CurrentDomain.Evidence;
SandboxDomain = AppDomain.CreateDomain("Sandbox", evidence, appDomainSetup);

CompiledFunction<T> result = (CompiledFunction<T>)SandboxDomain.CreateInstanceAndUnwrap(
    assemblyName: typeof(CompiledFunction<T>).Assembly.GetName().Name,
    typeName: typeof(CompiledFunction<T>).FullName);

This works fine in a Console application, but in an ASP .NET MVC application I get the following exception - can anyone offer any suggestion as to why this is not working in a web app? The T parameter I am passing is System.Decimal

System.IO.FileLoadException was caught
  Message=The given assembly name or codebase, 'Ems.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null', was invalid.
  Source=mscorlib
  FileName=Ems.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
  FusionLog==== Pre-bind state information ===
LOG: User = EMSLaptop\PeterMorris
LOG: DisplayName = Ems.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = /C:/Users/PeterMorris/Documents/Visual Studio 2010/Projects/MvcApplication26/MvcApplication26/bin
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Found application configuration file (C:\Program Files\Common Files\Microsoft Shared\DevServer\10.0\WebDev.WebServer40.exe.Config).
LOG: Using application configuration file: C:\Program Files\Common Files\Microsoft Shared\DevServer\10.0\WebDev.WebServer40.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL /C:/Users/PeterMorris/Documents/Visual Studio 2010/Projects/MvcApplication26/MvcApplication26/bin/Ems.Scripting.DLL.

  StackTrace:
       at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
       at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
       at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)
       at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
       at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)
       at System.Activator.CreateInstance(String assemblyName, String typeName)
       at System.AppDomain.CreateInstance(String assemblyName, String typeName)
       at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
       at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
       at Ems.Scripting.CompilerService.Compile[T](String[] scripts, Dictionary`2 variableDefinitions, IEnumerable`1 referencedAssemblies, ICompiledFunction`1& function, IEnumerable`1& compilerErrors) in C:\Data\EMS\Lib\Ems.Scripting\CompilerService.cs:line 43
  InnerException: 
Was it helpful?

Solution

The problem was that the Assembly.Code base started with file:///{rest of path here} - when using Path.GetDirectoryName on such a path it replaces file:/// with a single forward slash; so you end up with "/c:\myfolder\myfile.dll"

Getting Uri to tell me the local path was the solution

if (SandboxDomain == null)
{
    var appDomainSetup = new AppDomainSetup();
    string appBase = typeof(CompilerService).Assembly.CodeBase;

    //Added the following line
    appBase = new Uri(appBase).LocalPath;
    appDomainSetup.ApplicationBase = Path.GetDirectoryName(appBase);
    var evidence = AppDomain.CurrentDomain.Evidence;
    SandboxDomain = AppDomain.CreateDomain("Sandbox", evidence, appDomainSetup);
}

OTHER TIPS

Looks like you did not properly copy Ems.Scripting assembly for web project or set wrong ApplicationBase for your new domain (more likely).

Path.GetDirectoryName call is suspicious in computing ApplicationBase property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top