0

After reading Larry Osterman's response on the very same issue I am trying to solve at the moment, I thought I had found the answer to my question.

For the record, the question was : how can I from .Net (non-WinRT) list the types in a WinRT assembly ( mine are .dll files apparently, not .Winmd)

I therefore used the following code snippet :

//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);

( found on https://gist.github.com/2920743)

Unfortunately, I get a non-zero HResult.

I referred to the documentation and found this :

HR_RESULT_FROM_WIN32(ERROR_NO_PACKAGE) The function was called from a process that is not in a Windows Store app.

Does that mean it is not possible to list the types from .Net (non-WinRT) at all ?

Community
  • 1
  • 1
Fabio Salvalai
  • 2,479
  • 17
  • 30

2 Answers2

2

RoGetMetaDataFile is used to load a metadata file from within an app package. It locates the metadata file in which the named type is defined, loads that metadata file, and returns an IMetaDataImport interface pointer that represents that metadata file.

From ordinary .NET code you can call RuntimeEnvironment.GetRuntimeInterfaceAsIntPtr (or GetRuntimeInterfaceAsObject) to get the current runtime's IMetaDataDispenser interface pointer, which can be used to load arbitrary modules for inspection.

From native code, you can call ICLRMetaHost::GetRuntime to load a runtime, then from that object call ICLRRuntimeInfo::GetInterface to get its IMetaDataDispenser interface pointer.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Thanks ! it sets me on the right path. I managed to get a metadatadispenser, and call OpenScope on it, getting a pointer to an IMetaDataImport interface. I guess now, i'll have to find out the C# declaration of the interface in order to call its method and inspect its insides. – Fabio Salvalai Oct 15 '12 at 21:15
1

RoGetMetaDataFile can be used from outside the app package, however it will only resolve system windows runtime types.

In order to resolve app specific types, you need to be running with "package identity" - in other words, in the context of a running application.

Larry Osterman
  • 16,086
  • 32
  • 60
  • Thank you Larry. When you are stating "in the context of a running application", you mean a WinRT application, right ? In that case, I guess this API isn't going to help me much, since I want to explore the types from within a T4 Template :S – Fabio Salvalai Oct 16 '12 at 19:37
  • Yes, a windows store application. When you're running a non store application, you don't have package identity. – Larry Osterman Oct 17 '12 at 04:59