Не удается загрузить сборку, созданную с помощью кода в новом домене приложения

#c# #.net #applicationdomain

Вопрос:

У меня есть asp.net приложение, которое генерирует сборки на лету из пользовательских сценариев. Все это работает хорошо, но теперь я хочу запустить сборку в домене изолированного приложения с ограниченными разрешениями. Когда я загружаю сборку в новый домен приложения, я получаю исключение

Не удалось загрузить файл или сборку ‘genb3336c1d82074079911fb70bd8bd7e65.dll, Версия=1.0.0.0, Культура=нейтральная, PublicKeyToken=null’ или одна из его зависимостей. Система не может найти указанный файл.

Пытаясь понять, что происходит, я сохранил сгенерированную сборку на диск и просто написал простое приложение со следующим кодом

 string path = @"test.dll";
byte[] buffer = File.ReadAllBytes(path);

var assembly = AppDomain.CurrentDomain.Load(buffer); //This works

var appDomain = AppDomain.CreateDomain("Test");
assembly = appDomain.Load(buffer); //Exception
 

Снова, когда я пытаюсь загрузить сборку в новом домене, я получаю то же исключение. Загрузка его в текущий домен работает нормально.

Затем я создал библиотеку классов, используя только класс и исходный код, из которого я сгенерировал dll. Исходный код минимален, 2 строки кода в методе. Теперь, когда я создаю и загружаю эту библиотеку dll в новом домене приложения, она загружается просто отлично.

Я открыл 2 библиотеки DLL в ILSpy, и они выглядят одинаково введите описание изображения здесь

Поэтому я понятия не имею, что не так с сгенерированной библиотекой dll. Я создаю сборку, используя следующий код.

 public class ScriptCompiler
{
    public static (byte[], byte[], Assembly) Compile((string Source, string Path)[] sources, string[] references, params Type[] types)
    {
        var assemblyName = "gen"   Guid.NewGuid().ToString().Replace("-", "")   ".dll";
        byte[] rawAssembly;
        byte[] rawPdb;

#if DEBUG
        var encoding = Encoding.UTF8;
        var symbolsName = Path.ChangeExtension(assemblyName, "pdb");

        var sourceTexts = sources
            .Select(s => new { Buffer = encoding.GetBytes(s.Source), s.Source, s.Path })
            .Select(b => new { SourceText = SourceText.From(b.Buffer, b.Buffer.Length, encoding, canBeEmbedded: true), b.Path });

        var syntaxTrees = sourceTexts
            .Select(s => new { Tree = CSharpSyntaxTree.ParseText(s.SourceText, new CSharpParseOptions(), s.Path), s.Path })
            .Select(t => new { Node = t.Tree.GetRoot() as CSharpSyntaxNode, t.Path })
            .Select(n => CSharpSyntaxTree.Create(n.Node, null, n.Path, encoding));

        var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithOptimizationLevel(OptimizationLevel.Debug);
#else
        var syntaxTrees =
            from source in sources.Select(s => s.Source)
            select CSharpSyntaxTree.ParseText(source);

        var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithOptimizationLevel(OptimizationLevel.Release);
#endif

        var typeRefs = new List<MetadataReference>();
        foreach (var type in types)
        {
            typeRefs.Add(MetadataReference.CreateFromFile(type.Assembly.Location));
        }

        var compilation = CSharpCompilation.Create(assemblyName,
            options: options,
            syntaxTrees: syntaxTrees,
            references: typeRefs.Union(references.Select(r => MetadataReference.CreateFromFile(r))));

        EmitResult emitResu<

        using (var peStream = new MemoryStream())
        using (var pdbStream = new MemoryStream())
        {
#if DEBUG
            emitResult = compilation.Emit(
                peStream: peStream,
                pdbStream: pdbStream,
                embeddedTexts: sourceTexts.Select(s => EmbeddedText.FromSource(s.Path, s.SourceText)),
                options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: symbolsName)
            );
#else
            emitResult = compilation.Emit(peStream: peStream);
#endif

            if (emitResult.Success)
            {
                rawAssembly = peStream.GetBuffer();
                rawPdb = pdbStream.GetBuffer();
                var assembly = Assembly.Load(rawAssembly, rawPdb);
                return (rawAssembly, rawPdb, assembly);
            }
        }

        var message = string.Join("rn", emitResult.Diagnostics);
        throw new ApplicationException(message);
    }
}
 

У кого-нибудь есть какие-нибудь идеи?

Правка: Это журнал слияний. Я не знаю, как это интерпретировать.

 === Pre-bind state information ===
LOG: DisplayName = genb3336c1d82074079911fb70bd8bd7e65.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Users/Admin/source/repos/LoadAssembly/LoadAssembly/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:UsersAdminsourcereposLoadAssemblyLoadAssemblybinDebugLoadAssembly.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:WindowsMicrosoft.NETFrameworkv4.0.30319configmachine.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 file:///C:/Users/Admin/source/repos/LoadAssembly/LoadAssembly/bin/Debug/genb3336c1d82074079911fb70bd8bd7e65.dll.DLL.
LOG: Attempting download of new URL file:///C:/Users/Admin/source/repos/LoadAssembly/LoadAssembly/bin/Debug/genb3336c1d82074079911fb70bd8bd7e65.dll/genb3336c1d82074079911fb70bd8bd7e65.dll.DLL.
LOG: Attempting download of new URL file:///C:/Users/Admin/source/repos/LoadAssembly/LoadAssembly/bin/Debug/genb3336c1d82074079911fb70bd8bd7e65.dll.EXE.
LOG: Attempting download of new URL file:///C:/Users/Admin/source/repos/LoadAssembly/LoadAssembly/bin/Debug/genb3336c1d82074079911fb70bd8bd7e65.dll/genb3336c1d82074079911fb70bd8bd7e65.dll.EXE.
 

Комментарии:

1. Может быть, вы можете включить FusionLog, вы увидите, где он ищет файл и почему он его не нашел.

2. @Ygalbel Добавил FusionLog из исключения

3. Спасибо. Можете ли вы добавить fusionlog для успешного случая?

4. @Ygalbel Я не знаю, как это сделать. Пробовал с Fuslogvw, но ничего не показывает. Однако я переименовал dll, как путь в «Попытка загрузки…», и это работает. Это приводит меня в замешательство, так как я загружаю сборку из байтов.