Calling AppDomain.DoCallback from Powershell

后端 未结 2 1457
暗喜
暗喜 2021-01-20 02:10

This is based on the Stack Overflow question: How to load an assembly as reflection-only in a new AppDomain?

I am attempting to determine the runtime version of an a

2条回答
  •  孤独总比滥情好
    2021-01-20 03:02

    You can't run DoCallback via powershell alone. But DoCallBack does work with some inline C#. As Jeroen says it's ugly, but this works:

    $assm = "C:\temp\so\bin\dynamic-assembly.dll"
    
    Add-Type -TypeDefinition @"
    
    using System.Reflection;
    using System;
    
    namespace Example
    {
    
    
        public class AppDomainUtil
        {
    
    
            public void LoadInAppDomain(AppDomain childDomain, string assemblyName)
            {
                childDomain.SetData("assemblyName", assemblyName);
    
                childDomain.DoCallBack( new CrossAppDomainDelegate(LoadAssembly)) ;
            }
    
            public static void LoadAssembly() 
            {
    
                string assemblyName = (string)AppDomain.CurrentDomain.GetData("assemblyName");
    
                // console not available from another domain
                string log = "c:\\temp\\hello.txt";
    
                System.IO.File.WriteAllText(log, string.Format("Hello from {0}\r\n",AppDomain.CurrentDomain.FriendlyName));
    
                System.IO.File.AppendAllText(log, string.Format("Assembly to load is {0}\r\n",assemblyName));
    
                Assembly loaded = Assembly.Load(assemblyName);
    
                System.IO.File.AppendAllText(log, string.Format("Assemblyloaded: {0}\r\n",loaded.FullName));
            }
    
        }
    
    
    
    }
    "@ -OutputAssembly $assm -OutputType Library # must set output assembly otherwise assembly generated in-memory and it will break with Type errors.
    
    Add-Type -Path $assm
    
    function Load-AssemblyInNewAppDomain([string]$assembly) {
    
        Write-Host "Parent domain: $([AppDomain]::CurrentDomain.FriendlyName)"
    
        $util = New-Object Example.AppDomainUtil
    
        $ads = New-Object System.AppDomainSetup
    
        $cd = [AppDomain]::CurrentDomain
    
        # set application base 
        $ads.ApplicationBase =  [IO.path]::GetDirectoryName( $assm )
    
        [System.AppDomain]$newDomain = [System.AppDomain]::CreateDomain([System.Guid]::NewGuid().ToString(), $null, $ads);
        Write-Host "Created child domain: $($newDomain.FriendlyName)"
    
        $util.LoadInAppDomain($newDomain, $assembly)
    }
    

    Testing it out:

    PS C:\WINDOWS\system32> Load-AssemblyInNewAppDomain "".GetType().Assembly.FullName
    
    Parent domain: PowerShell_ISE.exe
    Created child domain: 61ab2dbb-8b33-4e7e-84db-5fabfded53aa
    
    PS C:\WINDOWS\system32> cat C:\temp\hello.txt
    
    Hello from 61ab2dbb-8b33-4e7e-84db-5fabfded53aa
    Assembly to load is mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    Assemblyloaded: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    

提交回复
热议问题