How do I load an assembly as a reflection in a new AppDomain only?

I have experience in C # but relatively unfamiliar with concepts AppDomain

and the like. Anyway, I'm trying to put the assembly in a reflection-only context so that I can grab all of its namespaces. Here is the code I have right now (warning: PowerShell):

function Get-Namespaces($assembly)
{
    $assemblyClass = [Reflection.Assembly]
    $winmdClass = [Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata]
    $domain = [AppDomain]::CurrentDomain

    # Since desktop .NET can't work with winmd files,
    # we have to use the reflection-only APIs and preload
    # all the dependencies manually.
    $appDomainHandler =
    {
        Param($sender, $e);
        $assemblyClass::ReflectionOnlyLoad($e.Name)
    }

    $winmdHandler =
    {
        Param($sender, $e)
        [string[]] $empty = @()
        $path = $winmdClass::ResolveNamespace($e.NamespaceName, $empty) | select -Index 0
        $e.ResolvedAssemblies.Add($assemblyClass::ReflectionOnlyLoadFrom($path))
    }

    # Hook up the handlers
    $domain.add_ReflectionOnlyAssemblyResolve($appDomainHandler)
    $winmdClass::add_ReflectionOnlyNamespaceResolve($winmdHandler)

    # Do the actual work
    $assemblyObject = $assemblyClass::ReflectionOnlyLoadFrom($assembly)
    $types = $assemblyObject.GetTypes()
    $namespaces = $types | ? IsPublic | select Namespace -Unique

    # Deregister the handlers
    $domain.remove_ReflectionOnlyAssemblyResolve($appDomainHandler)
    $winmdClass::remove_ReflectionOnlyNamespaceResolve($winmdHandler)

    return $namespaces
}

      

For some reason, when I run a function on assemblies like System.Xaml

or WindowsBase

, I get the following errors:

Exception calling "ReflectionOnlyLoadFrom" with "1" argument (s): "API restriction:
The assembly 'file: /// C: \ Program Files (x86) \ Reference Assemblies \ Microsoft \
Framework \ .NETFramework \ v4.6.1 \ System.Xaml.dll 'has already loaded from a
different location. It cannot be loaded from a new location within the same
appdomain. "
At C: \ Users \ James \ Code \ csharp \ Shims.Xaml \ generate.ps1: 50 char: 5
+ $ assemblyObject = $ assemblyClass :: ReflectionOnlyLoadFrom ($ assembl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
    + CategoryInfo: NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId: FileLoadException

So I would like to know how can I load the assembly in the new AppDomain? I checked MSDN but all I can find are methods like CreateInstanceAndUnwrap

which I can't / don't want to do as this is only reflection.

TL; DR: How do I load assemblies in a reflection-only context in a new AppDomain? Both C # and PowerShell code examples are welcome.


EDIT: Here is a GitHub gist script I made so others can reproduce the bug / test changes.

+2


source to share


1 answer


I think I got it this way:



function Load-AssemblyInNewAppDomain($assembly)
{
    $domain = [AppDomain]::CreateDomain("foo")
    $domain.DoCallback
    ({
        $loaded = [Reflection.Assembly]::Load($assembly)
    })
}

      

0


source







All Articles