📄 typelibimporter.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Poul Staugaard" email="poul@staugaard.dk"/>
// <version value="$version"/>
// </file>
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.Win32;
namespace ICSharpCode.SharpDevelop.Internal.Project
{
/// <summary>
/// Wraps code to import a typelibrary
/// </summary>
/// <remarks>
/// created by - Poul Staugaard
/// created on - 17-08-2002 14:24:13
/// </remarks>
public class TypelibImporter
{
enum RegKind {
RegKind_Default = 0,
RegKind_Register = 1,
RegKind_None = 2
}
[DllImport( "oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void LoadTypeLibEx(string strTypeLibName, RegKind regKind, [MarshalAs(UnmanagedType.Interface)] out Object typeLib);
/// <summary>
/// Default constructor - initializes all fields to default values
/// </summary>
public TypelibImporter()
{
}
public string Import(ProjectReference refinfo, IProject project)
{
RegistryKey root = Registry.ClassesRoot;
RegistryKey typelibsKey = root.OpenSubKey("TypeLib");
int index = refinfo.Reference.LastIndexOf("{");
if (index < 0) {
return null;
}
RegistryKey typelibKey = typelibsKey.OpenSubKey(refinfo.Reference.Substring(index, refinfo.Reference.Length - index));
if (typelibKey == null) {
return null;
}
string[] versions = typelibKey.GetSubKeyNames();
if (versions.Length <= 0) {
return null;
}
// Use the last version
string version = versions[versions.Length - 1];
RegistryKey versionKey = typelibKey.OpenSubKey(version);
string tlbname = (string)versionKey.GetValue(null);
string tlpath = GetTypelibPath(versionKey);
if (tlpath == null) {
return null;
}
string proxyfilename = "Interop." + Path.GetFileNameWithoutExtension(tlpath) + ".dll";
AbstractProjectConfiguration ac = (AbstractProjectConfiguration)project.ActiveConfiguration;
string fullpath = Path.Combine(ac.OutputDirectory,proxyfilename);
if (!File.Exists(fullpath)) {
string saveCurrDir = Directory.GetCurrentDirectory();
if (!Directory.Exists(ac.OutputDirectory)) {
Directory.CreateDirectory(ac.OutputDirectory);
}
Directory.SetCurrentDirectory(ac.OutputDirectory);
if (!ImportTypelibUsingTlbImpCode(tlpath, ac.OutputDirectory, proxyfilename)) {
MessageBox.Show("Cannot import type library using .Net SDK 1.0. Some, but not all type libraries can succesfully be imported without it. ",
".Net SDK 1.0 not present ?",
MessageBoxButtons.OK,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button1);
Object typeLib;
LoadTypeLibEx(tlpath, RegKind.RegKind_None, out typeLib);
if( typeLib == null ) {
throw new System.Exception("LoadTypeLibEx failed.");
}
TypeLibConverter converter = new TypeLibConverter();
ConversionEventHandler eventHandler = new ConversionEventHandler();
AssemblyBuilder asm = converter.ConvertTypeLibToAssembly( typeLib,
proxyfilename, 0, eventHandler, null, null,
Marshal.GetTypeLibName((UCOMITypeLib)typeLib), null );
asm.Save( proxyfilename );
}
Directory.SetCurrentDirectory(saveCurrDir);
}
return fullpath;
}
string GetTypelibName(string tlpath)
{
Object typeLib;
LoadTypeLibEx(tlpath, RegKind.RegKind_None, out typeLib);
if( typeLib == null ) {
throw new System.Exception("LoadTypeLibEx failed.");
}
return Marshal.GetTypeLibName((UCOMITypeLib)typeLib);
}
bool ImportTypelibUsingTlbImpCode(string typelibfile, string outputpath, string assemblyname)
{
// TlbImpCode being an undocumented assembly which is only installed with the .Net SDK,
// use late binding in stead of <iso> to allow the app as a whole to run even if,
// in its absense, this does not work:
try {
//<iso> TlbImpCode.TlbImpOptions options = new TlbImpCode.TlbImpOptions(); </iso>
Assembly assyTic = Assembly.LoadWithPartialName("TlbImpCode, Version=1.0");
Type optype = assyTic.GetType("TlbImpCode.TlbImpOptions");
object options = Activator.CreateInstance(optype);
//<iso> options.m_strOutputDir = outputpath; </iso>
optype.GetField("m_strOutputDir").SetValue(options, outputpath);
//<iso> options.m_strTypeLibName = typelibfile; </iso>
optype.GetField("m_strTypeLibName").SetValue(options, typelibfile);
//<iso> options.m_strAssemblyName = assemblyname; </iso>
optype.GetField("m_strAssemblyName").SetValue(options, assemblyname);
//<iso> options.m_strAssemblyNamespace = GetTypelibName(typelibfile); </iso>
optype.GetField("m_strAssemblyNamespace").SetValue(options, GetTypelibName(typelibfile));
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = outputpath;
AppDomain ad = AppDomain.CreateDomain("TlbImport", null, ads);
if (ad == null)
throw new Exception("Failed to create AppDomain");
//<iso> string remoteTlbImpAssemblyName =
// typeof(TlbImpCode.RemoteTlbImp).Assembly.GetName().FullName; </iso>
string remoteTlbImpAssemblyName = assyTic.GetName().FullName;
//<iso> TlbImpCode.RemoteTlbImp tic = (TlbImpCode.RemoteTlbImp) ...</iso>
object tic = ad.CreateInstanceAndUnwrap(remoteTlbImpAssemblyName, "TlbImpCode.RemoteTlbImp");
//<iso> tic.Run(options); </osi>
Type tictype = tic.GetType();
MethodInfo miRun = tictype.GetMethod("Run");
object[] targs = new object[1];
targs[0] = options;
miRun.Invoke(tic, targs);
return true;
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
return false;
}
string GetTypelibPath(RegistryKey versionKey)
{
// Get the default value of the (typically) 0\win32 subkey:
string[] subkeys = versionKey.GetSubKeyNames();
if (subkeys == null || subkeys.Length == 0) {
return null;
}
for (int i = 0; i < subkeys.Length; i++)
{
try {
int.Parse(subkeys[i]); // The right key is a number
RegistryKey NullKey = versionKey.OpenSubKey( subkeys[i]);
string[] subsubkeys = NullKey.GetSubKeyNames();
RegistryKey win32Key = NullKey.OpenSubKey("win32");
return win32Key == null || win32Key.GetValue(null) == null ?
null : win32Key.GetValue(null).ToString();
}
catch (FormatException) {
// Wrong keys don't parse til int
}
}
return null;
}
public class ConversionEventHandler : ITypeLibImporterNotifySink
{
public void ReportEvent( ImporterEventKind eventKind, int eventCode, string eventMsg )
{
// handle warning event here...
}
public Assembly ResolveRef( object typeLib )
{
// resolve reference here and return a correct assembly...
return null;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -