在我正在尝试解决的同一问题上阅读Larry Osterman's response后,我以为我找到了问题的答案。
为了记录,问题是:我如何从.Net(非WinRT)列出WinRT程序集中的类型(我的.dll文件显然是,但不是.Winmd)
因此我使用了以下代码片段:
//note, this wrapper function returns the metadata file name and token
// it immediately releases the importer pointer
static Tuple<string, UInt32> ResolveTypeName(string typename)
{
string path;
object importer = null;
UInt32 token;
try
{
var hr = RoGetMetaDataFile(typename, IntPtr.Zero, out path, out importer, out token);
//TODO: check HR for error
return Tuple.Create(path, token);
}
finally
{
Marshal.ReleaseComObject(importer);
}
}
[DllImport("WinTypes.dll")]
static extern UInt32 RoGetMetaDataFile(
[MarshalAs(UnmanagedType.HString)] string name,
IntPtr metaDataDispenser,
[MarshalAs(UnmanagedType.HString)] out string metaDataFilePath,
[MarshalAs(UnmanagedType.Interface)] out object metaDataImport,
out UInt32 typeDefToken);
(见https://gist.github.com/2920743)
不幸的是,我得到了一个非零的HResult。
我参考了文档,发现了这个:
HR_RESULT_FROM_WIN32(ERROR_NO_PACKAGE)该函数是从a调用的 不属于Windows应用商店应用的流程。
这是否意味着根本无法列出.Net(非WinRT)的类型?
答案 0 :(得分:2)
RoGetMetaDataFile
用于从应用包中加载元数据文件。它找到定义了命名类型的元数据文件,加载该元数据文件,并返回表示该元数据文件的IMetaDataImport
接口指针。
从普通的.NET代码中,您可以调用RuntimeEnvironment.GetRuntimeInterfaceAsIntPtr
(或GetRuntimeInterfaceAsObject
)来获取当前运行时的IMetaDataDispenser
接口指针,该指针可用于加载任意模块以供检查。
从本机代码中,您可以调用ICLRMetaHost::GetRuntime
来加载运行时,然后从该对象调用ICLRRuntimeInfo::GetInterface
来获取其IMetaDataDispenser
接口指针。
答案 1 :(得分:1)
RoGetMetaDataFile
,但它只能解析系统窗口运行时类型。
为了解析特定于应用的类型,您需要使用“包标识”运行 - 换句话说,在正在运行的应用程序的上下文中运行。