powershell - 如何在 PowerShell 中从 mscoree.tlb 实例化 CorRuntimeHost?

标签 powershell com clr appdomain

我想从 PowerShell 枚举当前进程中的所有 AppDomain。该进程恰好是 Visual Studio,它托管 StudioShell 。为此,我需要实例化 CorRuntimHost,它是 mscoree.tlb 的一部分,这样我就可以调整 this C# code ..

我尝试获取 CorRunTimeHost 的正确名称并将其传递给 New-Object -COMObject "objectName" 。基于this forum posting ,我搜索了注册表,我认为正确的名称是CLRMetaData.CorRuntimeHost。但是,虽然 New-Object -ComObject 'CLRMetaData.CorRuntimeHost' -Strict 确实返回一个对象,但它仅公开 COM 对象固有的方法。

基于this stackoverflow question我试过[Activator]::CreateInstance() 。但是,以下两条语句给了我与 New-Object 相同的问题,即我无法调用 ICorRuntimeHost::EnumDomains()方法。

$corRuntimeHost = [Activator]::CreateInstance([Type]::GetTypeFromProgID('CLRMetaData.CorRuntimeHost'));
$enumerator = $null;
$corRuntimeHost.EnumDomains([ref]$enumerator);

Method invocation failed because [System.__ComObject] doesn't contain a method named 'EnumDomains'.
At line:1 char:1
+ $corRuntimeHost.EnumDomains([ref]$enumerator)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

最佳答案

为了让它在 PowerShell 3.0 中工作,我最终不得不使用 AssemblyBuilder 。下面是工作代码:

问题似乎是 mscoree.CorRuntimeHostClass 没有公共(public)构造函数在 .NET 4.0 中存在,但在 3.5 中存在。

我后来在带有 powershell 2.0 的 Windows 7 VM 上测试了此代码,现在此代码可以在 PowerShell 2.0 和 3.0 中运行。

$tlbName = Split-Path -Parent ([AppDomain]::CurrentDomain.GetAssemblies() | Where { $_.Location -Match '\\mscorlib.dll$' }).Location 
$tlbName = Join-Path $tlbName 'mscoree.tlb';

$csharpString = @"
//adapted from here http://blog.semanticsworks.com/2008/04/enumerating-appdomains.html
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;

public class ListProcessAppDomains
{

    [DllImport( `"oleaut32.dll`", CharSet = CharSet.Unicode, PreserveSig = false )]
    private static extern void LoadTypeLibEx
        (String strTypeLibName, RegKind regKind, 
         [MarshalAs( UnmanagedType.Interface )] out Object typeLib);

    private enum RegKind
    {
        Default = 0,
        Register = 1,
        None = 2
    }

    private class ConversionEventHandler : ITypeLibImporterNotifySink
    {
        public void ReportEvent( ImporterEventKind eventKind, int eventCode, string eventMsg )
        {
            Console.Error.WriteLine("Kind: {0} Code: {1} Message");
        }

        public Assembly ResolveRef( object typeLib )
        {
            string stackTrace = System.Environment.StackTrace;
            Console.WriteLine("ResolveRef ({0})", typeLib);
            Console.WriteLine(stackTrace);
          return null; 
        }    
    }

    public static AssemblyBuilder LoadMsCoreeDll( ref Object typeLib ) {
        ConversionEventHandler eventHandler = new ConversionEventHandler();
        string assemblyName = "PoshComWrapper.dll";
        LoadTypeLibEx( @"$($tlbName)", RegKind.None, out typeLib ); 
        TypeLibConverter typeLibConverter = new TypeLibConverter();
        return typeLibConverter.ConvertTypeLibToAssembly( typeLib, assemblyName, 0, eventHandler, null, null, null, null );
    }
}
"@

# So we can run this scipt multiple times
try { [ListProcessAppDomains] } catch {  Add-Type -TypeDefinition $csharpString }

function Get-AppDomain {
    $typeLib = $null;
    $assemblyBuilder = [ListProcessAppDomains]::LoadMsCoreeDll([ref] $typeLib)
    $corRuntimeHostClass = $assemblyBuilder.CreateInstance('PoshComWrapper.CorRuntimeHostClass')
    $enumHandle = [IntPtr]::Zero
    $corRuntimeHostClass.EnumDomains([ref] $enumHandle);
    $appDomain = $null;
    do
    {
        $corRuntimeHostClass.NextDomain($enumHandle, [ref] $appDomain);
        if ($appDomain -ne $null -and $appDomain.GetType() -eq [AppDomain]) { $appDomain; }
    } while ($appDomain -ne $null)
}

Get-AppDomain 

关于powershell - 如何在 PowerShell 中从 mscoree.tlb 实例化 CorRuntimeHost?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16513608/

相关文章:

c# - 在 C++ dll 中使用 COM 对象

.NET集合和大对象堆(LOH)

windows - Windows : how to read Unicode input from console? 上的 GHCi

powershell - 如何使用powershell运行批处理文件

powershell - 环境变量未正确实现

c++ - 哪个是对的?捕获(_com_error e)还是捕获(_com_error& e)?

c++ - 嵌入式 IWebBrowser2 中的 DocumentComplete 事件使用 write() 方法

c++ - 正确测量像素中的字符

.net - CLR 如何实现 COM 实现的二进制级别的互操作性?或者不?

powershell - 只保留前 3 项