Skip to content

Instantly share code, notes, and snippets.

@zippy1981
Last active December 17, 2015 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zippy1981/a838ff74196acce66d7e to your computer and use it in GitHub Desktop.
Save zippy1981/a838ff74196acce66d7e to your computer and use it in GitHub Desktop.
My attempts to get mscoree.tlb loaded at runtime with powershell. The working code is EnumAppDomains.ps1
# adapted from here http://blog.semanticsworks.com/2008/04/enumerating-appdomains.html
$csharpString = @"
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class ListProcessAppDomains
{
private static extern void LoadTypeLibEx
(String strTypeLibName, RegKind regKind,
[MarshalAs( UnmanagedType.Interface )] out Object typeLib);
private enum RegKind
{
RegKind_Default = 0,
RegKind_Register = 1,
RegKind_None = 2
}
private class ConversionEventHandler : ITypeLibImporterNotifySink
{
private void ReportEvent( ImporterEventKind eventKind, int eventCode, string eventMsg )
{
Console.Error.WriteLine("Kind: {0} Code: {1} Message");
}
public Assembly ResolveRef( object typeLib )
{
// resolve reference here and return a correct assembly...
//This is where im not sure how to do it
return null;
}
}
static ListProcessAppDomains() {
}
public static IList<AppDomain> GetAppDomains()
{
var appDomains = new List<AppDomain>();
IntPtr enumHandle = IntPtr.Zero;
dynamic host = Activator.CreateInstance(Type.GetTypeFromProgID("CLRMetaData.CorRuntimeHost"));
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while (true)
{
host.NextDomain(enumHandle, out domain);
if (domain == null) break;
AppDomain appDomain = (AppDomain)domain;
appDomains.Add(appDomain);
}
return appDomains;
}
catch (Exception e)
{
Console.Error.WriteLine(e.ToString());
return null;
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
}
}
}
"@
Add-Type -TypeDefinition $csharpString
$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
$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 )
{
var stackTrace = System.Environment.StackTrace;
Console.WriteLine("ResolveRef ({0})", typeLib);
Console.WriteLine(stackTrace);
return null;
}
}
public static AssemblyBuilder LoadMsCoreeDll( ref Object typeLib ) {
var eventHandler = new ConversionEventHandler();
var assemblyName = "PoshComWrapper.dll";
LoadTypeLibEx( @"$($tlbName)", RegKind.None, out typeLib );
var 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
Add-Type -Namespace "JustAProgramer" -Name 'LoadTypeHelper' -MemberDefinition "[ DllImport( `"oleaut32.dll`", CharSet = CharSet.Unicode, PreserveSig = false )]
public static extern void LoadTypeLibEx( String strTypeLibName, RegKind regKind,
[ MarshalAs( UnmanagedType.Interface )] out Object typeLib );
public enum RegKind
{
RegKind_Default = 0,
RegKind_Register = 1,
RegKind_None = 2
}"
$tlbName = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoree.tlb';
$dllName = [IO.Path]::GetTempFileName()
$typeLibConverter = New-Object Runtime.InteropServices.TypeLibConverter
$typeLib = $null;
[JustAProgramer.LoadTypeHelper]::LoadTypeLibEx( $tlbName, [JustAProgramer.LoadTypeHelper+RegKind]::RegKind_None, [ref] $typeLib );
#$typeLibConverter | gm
#$typeLibConverter.ConvertTypeLibToAssembly
$typeLib
[AssemblyBuilder] $asm = $typeLibConverter.ConvertTypeLibToAssembly($typeLib, $dllName, 0, $null, $null, $null, $null, $null );
$asm.Save( "ExplorerLib.dll" );
if (Test-Path $dllName) {
rm -Force $dllName
}
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using mscoree;
// This code does not work in .NET 4.0. It does compile in .NET 3.5
namespace ConsoleApplication2
{
internal static class Program
{
static void Main()
{
foreach (var appDomain in GetAppDomains())
{
Console.WriteLine("Name: {0} Id: {1} Config file: {2}", appDomain.FriendlyName, appDomain.Id, appDomain.SetupInformation.ConfigurationFile);
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
private static IList<AppDomain> GetAppDomains()
{
var appDomains = new List<AppDomain>();
IntPtr enumHandle = IntPtr.Zero;
var host = new CorRuntimeHostClass();
try
{
host.EnumDomains(out enumHandle);
object domain;
do
{
host.NextDomain(enumHandle, out domain);
if (domain == null) break;
var appDomain = (AppDomain) domain;
appDomains.Add(appDomain);
} while (domain != null);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return null;
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
}
return appDomains;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment