Getting the full display name of an assembly given the path to the manifest file

Given a path to an assembly manifest file, how do we get its full display name, including ProcessorArchitecture?

From my previous discussion, we know there is no managed way to achieve this. We have to use an unmanaged solution.

From the discussion of assembly identity, we know that identities can be reference or definition. In unmanaged fusion we exposed a full programming model on assembly identity. Specifically, we introduced three interfaces: IReferenceIdentity, IDefinitionIdentity, and IIdentityAuthority. IReferenceIdenity represents an assembly reference. IDefinitionIdentity is an assembly definition. IIdentityAuthority is used to compare identities, as well as map the identities and their textual representation (so called assembly display name).

The three interfaces are defined in isolation.h, which is part of .Net framework 2.0 SDK.

The following sample uses those interfaces to get the full display name of an assembly given its path.

//
// ShowName.cpp
//
// Show the full display name of an given assembly, including architecture.
//

#include "fusion.h"
#include "windows.h"
#include "stdio.h"
#include "mscoree.h"
#include "isolation.h"

typedef HRESULT (__stdcall *PFNGETREF)(LPCWSTR pwzFile, REFIID riid, IUnknown **ppUnk);
typedef HRESULT (__stdcall *PFNGETAUTH)(IIdentityAuthority **ppIIdentityAuthority);

PFNGETREF g_pfnGetAssemblyIdentityFromFile = NULL;
PFNGETAUTH g_pfnGetIdentityAuthority = NULL;
IUnknown *g_pUnk = NULL;

bool Init()
{
HRESULT hr = S_OK;
DWORD dwSize = 0;
bool bRC = false;

hr = CorBindToRuntimeEx(NULL, L"wks", 0, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (void **)&g_pUnk);
if(FAILED(hr)) {
printf("Error: Failed to initialize CLR runtime! hr = 0x%0x\n", hr);
goto Exit;
}

if (SUCCEEDED(hr)) {
hr = GetRealProcAddress("GetAssemblyIdentityFromFile", (VOID **)&g_pfnGetAssemblyIdentityFromFile);
}

    if (SUCCEEDED(hr)) {
hr = GetRealProcAddress("GetIdentityAuthority", (VOID **)&g_pfnGetIdentityAuthority);
}

    if (!g_pfnGetAssemblyIdentityFromFile || !g_pfnGetIdentityAuthority) {
printf("Error: Cannot get required APIs from fusion.dll!\n");
goto Exit;
}

    bRC = true;

Exit:
return bRC;
}

void Shutdown()
{
if(g_pUnk) {
g_pUnk->Release();
g_pUnk = NULL;
}
}

void Usage()
{
printf("ShowName: A tool to show the display name of a given assembly.\n\n");
printf("Usage: ShowName AsmFilePath\n");
printf("\n");
}

int _cdecl wmain(int argc, LPCWSTR argv[])
{
int iResult = 1;
IUnknown *pUnk = NULL;
IReferenceIdentity *pRef = NULL;
IIdentityAuthority *pAuth = NULL;
WCHAR Buffer[1024];
DWORD dwSize = sizeof(Buffer)/sizeof(WCHAR);
HRESULT hr = S_OK;
  

    if(argc != 2) {
Usage();
goto Exit;
}

    if(!Init()) {
printf("Failure initializing ShowName.\n");
goto Exit;
}

    hr = g_pfnGetAssemblyIdentityFromFile(argv[1], __uuidof(IReferenceIdentity), &pUnk);
if (FAILED(hr)) {
printf("GetAssemblyIdentityFromFile failed with hr = 0x%x", hr);
goto Exit;
}

    hr = pUnk->QueryInterface(__uuidof(IReferenceIdentity), (void**)&pRef);
if (FAILED(hr)) {
goto Exit;
}

    hr = g_pfnGetIdentityAuthority(&pAuth);
if (FAILED(hr)) {
goto Exit;
}

    hr = pAuth->ReferenceToTextBuffer(0, pRef, dwSize, Buffer, &dwSize);
if (FAILED(hr)) {
printf("ReferenceToTextBuffer failed with hr = 0x%x.\n", hr);
goto Exit;
}

    printf("Assembly Identity of %ws is:\n", argv[1]);
printf("%ws\n", Buffer);

    iResult = 0;

Exit:

    Shutdown();

    if (pUnk) {
pUnk->Release();
}

    if (pRef) {
pRef->Release();
}

   if (pAuth) {
pAuth->Release();
}

    return iResult;
}

Here is some sample output:

C:>showname C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\system.dll
Assembly Identity of C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\system.dll is:
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL