Fusion GAC API Samples
For displaying purpose, error handling is skipped in all the sample code. Please don’t skip error handling in production code.
1.1. Get GAC API Interfaces
Before use GAC API interfaces, you have to get GAC API interfaces.
GAC API interfaces are pseudo COM like. You need to call AddRef() and Release() when appropriate. But you can not get the interfaces by calling CoCreateInstance(). Instead, fusion.dll provides several exports to get those interfaces.
There is no lib file provided for fusion’s exports. The reason is simple: fusion.dll lives in .net framework directory, which by default is not in path. If we provided a fusion.lib, and you used it, NT loader will not be able to load fusion.dll for you.
The right way to get fusion’s exports is to use mscoree!LoadLibraryShim to locate fusion.dll, then call GetProcAddress().
The following is a sample code to get fusion’s exports:
#include “mscoree.h”
#include “fusion.h”
typedef HRESULT (__stdcall *CreateAsmCache)(IAssemblyCache **ppAsmCache, DWORD dwReserved);
typedef HRESULT (__stdcall *CreateAsmNameObj)(LPASSEMBLYNAME *ppAssemblyNameObj, LPCWSTR szAssemblyName, DWORD dwFlags, LPVOID pvReserved);
typedef HRESULT (__stdcall *CreateAsmEnum)(IAssemblyEnum **pEnum, IUnknown *pAppCtx, IAssemblyName *pName, DWORD dwFlags, LPVOID pvReserved);
HMODULE g_FusionDll = NULL;
CreateAsmCache g_pfnCreateAssemblyCache = NULL;
CreateAsmNameObj g_pfnCreateAssemblyNameObject = NULL;
CreateAsmEnum g_pfnCreateAssemblyEnum = NULL;
LoadLibraryShim(L"fusion.dll", 0, 0, &g_FusionDll);
g_pfnCreateAssemblyCache = (CreateAsmCache)GetProcAddress(g_FusionDll, CreateAssemblyCache");
g_pfnCreateAssemblyNameObject = (CreateAsmNameObj)GetProcAddress(g_FusionDll, “CreateAssemblyNameObject");
g_pfnCreateAssemblyEnum = (CreateAsmEnum)GetProcAddress(g_FusionDll, CreateAssemblyEnum");
You need to link against mscoree.lib, which is included in .Net framework SDK.
All the sample code below assumes you have initialized GAC API interfaces.
1.2. Install Assembly without Trace Reference
It is recommended that you install an assembly with reference. But the sample code of installing assembly without reference is included for illustration purpose.
// Get an IAssemblyCache interface
IAssemblyCache* pCache = NULL;
g_pfnCreateAssemblyCache(&pCache, 0);
// call IAssemblyCache::InstallAssembly
HRESULT hr = pCache->InstallAssembly(0, pszAssemblyFilePath, NULL);
// Report result based on the return hr.
1.3. Install Assembly with Trace Reference
// Create an FUSION_INSTALL_REFERENCE struct and fill it with data
FUSION_INSTALL_REFERENCE installReference;
Memset(&installReference, 0, sizeof(FUSION_INSTALL_REFERENCE);
installReference.cbSize= sizeof(FUSION_INSTALL_REFERENCE);
installReference.dwFlags=0;
// We use opaque scheme here
installReference.guidSchem = FUSION_REFCOUNT_OPAQUE_STRING_GUID;
installReference.szIdentifier = L”Your Application Identifier goes here”;
installReference.szNonCannonicalData= L”Informational Description goes here”;
// Get an IAssemblyCache interface
IAssemblyCache* pCache = NULL;
g_pfnCreateAssemblyCache(&pCache, 0);
// call IAssemblyCache::InstallAssembly with reference
HRESULT hr = pCache->InstallAssembly(0, pszAssemblyFilePath, &installReference);
pCache->Release();
// Report result based on the return hr.
1.4. Uninstall Assembly with Trace Reference
// Create an FUSION_INSTALL_REFERENCE struct and fill it with data
FUSION_INSTALL_REFERENCE installReference = NULL;
installReference.cbSize= sizeof(FUSION_INSTALL_REFERENCE);
installReference.dwFlags=0;
// We use opaque scheme here
installReference.guidSchem = FUSION_REFCOUNT_OPAQUE_STRING_GUID;
installReference.szIdentifier = L”Your Application Identifier goes here”;
installReference.szNonCannonicalData= L”Informational Description goes here”;
// Get an IAssemblyCache interface
IAssemblyCache* pCache = NULL;
g_pfnCreateAssemblyCache(&pCache, 0);
// call IAssemblyCache::UninstallAssembly with reference
// UninstallAssembly takes a fully specified (including processor architecture) assembly name as input.
LPWSTR pszAssemblyName = L”MyAssembly, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=0123456789abcdef, ProcessorArchitecture=MSIL”;
ULONG ulDisp = 0;
HRESULT hr = pCache->UninstallAssembly(0, pszAssemblyName, &installReference, &ulDisp);
pCache->Release();
// report result based on return hr and ulDisp.
1.5. Query Assembly in GAC
// Create an ASSEMBLY_INFO struct and fill it with data
ASSEMBLY_INFO info;
WCHAR path[MAX_PATH];
memset(&info, 0, sizeof(ASSEMBLY_INFO);
info.cbAssemblyInfo = sizeof(ASSEMBLY_INFO);
info.pszCurrentAssemblyPathBuf = path;
info.cchBuf = MAX_PATH;
// Get an IAssemblyCache interface
IAssemblyCache* pCache = NULL;
g_pfnCreateAssemblyCache(&pCache, 0);
// QueryAssemblyInfo takes a fully specified (including processor architecture) assembly name as input.
LPWSTR pszAssemblyName = L”MyAssembly, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=0123456789abcdef, ProcessorArchitecture=MSIL”;
HRESULT hr = pCache->QueryAssemblyInfo(0, pszAssemblyName, &info);
pCache->Release();
// path[] now contain the path of the assembly in GAC if QueryAssemblyInfo returns success
1.6. Enumerate Assembly in GAC
// Enumerate GAC for all the assembly “System”.
// “System” can be any valid assembly display name.
// If you want to see all assemblies, set pNameFilter to NULL
LPWSTR pszAssemblyName = L”System”;
IAssemblyName* pNameFilter = NULL;
IAssemblyEnum* pEnum = NULL;
IAssemblyName* pAsmName = NULL;
DWORD dwDisplayFlags = ASM_DISPLAYF_VERSION
| ASM_DISPLAYF_CULTURE
| ASM_DISPLAYF_PUBLIC_KEY_TOKEN
| ASM_DISPLAYF_PROCESSORARCHITECTURE;
DWORD dwLen = 0;
LPWSTR szDisplayName = NULL;
// First, create a filter for “system”
g_pfnCreateAssemblyNameObject(&pNameFilter, pszAssemblyName, CANOF_PARSE_DISPLAY_NAME, NULL);
// now create the IAssemblyEnum for GAC
g_pfnCreateAssemblyEnum(&pEnum, NULL, pNameFilter, ASM_CACHE_GAC, NULL);
// Enumerating.
// GetNextAssembly return S_OK when there are still assemblies exist for the enum,
// and S_FALSE if there is nothing left.
While (pEnum->GetNextAssembly(NULL, &pAsmName, 0) == S_OK)
{
// pAsmName is the assembly returned by the enum. Now let’s get its display name
dwLen = 0;
// get the size first.
pAsmName->GetDisplayName(NULL, &dwLen, dwDisplayFlags);
// allocate memory
szDisplayName = new WCHAR[dwLen];
// re-try
pAsmName->GetDisplayName(szDisplayName, &dwLen, dwDisplayFlags);
// show it
printf(“%S”, szDisplayName);
delete[] szDisplayName;
pAsmName->Release();
}
pEnum->Release();
pNameFilter->Release();