Exemplo n.º 1
0
// Try to get the right version of the CLR running.
HRESULT LoadClr(std::wstring clrVersion, ICorRuntimeHost **ppHost)
{
	// Check whether the .Net 4+ MetaHost interfaces are present.
	// The checks here are according to this blog post: 
	// http://bradwilson.typepad.com/blog/2010/04/selecting-clr-version-from-unmanaged-host.html
	/*
	1. LoadLibrary mscoree
	2. GetProcAddress for CLRCreateInstance. If you get NULL, fall back to legacy path (CorBindToRuntimeEx)
	3. Call CLRCreateInstance to get ICLRMetaHost. If you get E_NOTIMPL, fall back to legacy path (same as above)
	4. Otherwise, party on the ICLRMetaHost you just got
	*/
	// If present, load the desired version using the new interfaces.
	// If not, check if we want .Net 4+, if so fail, else load old-style.

	HRESULT hr = E_FAIL;
	HMODULE hMscoree = NULL;
	ICLRMetaHostPtr pMetaHost;

	bool needNet40 = (CompareNoCase(clrVersion, L"v4.0") >= 0);
	bool needMetaHost = needNet40;

	hMscoree = LoadLibrary(L"mscoree.dll");
	if (hMscoree == 0)
	{
		// No .Net installed
		// CONSIDER: Doing explicit checking according to http://support.microsoft.com/kb/318785
		if (needNet40)
		{
				ShowMessage(IDS_MSG_HEADER_NEEDCLR40, 
					IDS_MSG_BODY_LOADMSCOREE, 
					IDS_MSG_FOOTER_ENSURECLR40 );
		}
		else
		{
				ShowMessage(IDS_MSG_HEADER_NEEDCLR20, 
					IDS_MSG_BODY_LOADMSCOREE, 
					IDS_MSG_FOOTER_ENSURECLR20 );
		}
		hr = E_FAIL;
	}
	else
	{
		pfnCLRCreateInstance CLRCreateInstance = (pfnCLRCreateInstance)GetProcAddress(hMscoree, "CLRCreateInstance");
		if (CLRCreateInstance == 0)
		{
			// Certainly no .Net 4 installed
			if (needMetaHost)
			{
				// We need .Net 4.0 but it is not installed
				ShowMessage(IDS_MSG_HEADER_NEEDCLR40, 
							IDS_MSG_BODY_NOCLRCREATEINSTANCE, 
							IDS_MSG_FOOTER_ENSURECLR40 );
				hr = E_FAIL;
			}
			else
			{
				// We need only .Net 2.0 runtime and cannot MetaHost.
				// Load .Net 2.0 with old code path
				hr = LoadClr20(ppHost);
			}
		}
		else
		{
			hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
			if (FAILED(hr))
			{
				// MetaHost is not available, even though we have a new version of MSCorEE.dll
				// Certainly no .Net 4 installed
				if (needMetaHost)
				{
					// We need .Net 4.0 but it is not installed
					ShowMessage(IDS_MSG_HEADER_NEEDCLR40, 
								IDS_MSG_BODY_CLRCREATEINSTANCEFAILED, 
								IDS_MSG_FOOTER_ENSURECLR40, 
								hr );
					hr = E_FAIL;
				}
				else
				{
					// We need only .Net 2.0 runtime and cannot MetaHost.
					// Load .Net 2.0 with old code path
					hr = LoadClr20(ppHost);
				}
			}
			else
			{
				// Yay! We have a metahost
				hr = LoadClrMeta(clrVersion, pMetaHost, ppHost);
			}
		}
		FreeLibrary(hMscoree);
	}
	return hr;
}
Exemplo n.º 2
0
bool XlLibraryInitialize(XlAddInExportInfo* pExportInfo)
{
	HRESULT hr;
	CComPtr<ICorRuntimeHost> pHost;

	hr = LoadClr20(&pHost);
	if (FAILED(hr) || pHost == NULL)
	{
		// LoadClr20 shows diagnostic MessageBoxes if needed.
		// Perhaps remember that we are not loaded?
		return 0;
	}

	// If all is fine now, also start the CLR (always safe to do again.
	hr = pHost->Start();
	if (FAILED(hr))
	{
		ShowMessage(IDS_MSG_HEADER_NEEDCLR20, 
					IDS_MSG_BODY_HOSTSTART,
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return 0;
	}

	CString addInFullPath = AddInFullPath();

	CPath xllDirectory(addInFullPath);
	xllDirectory.RemoveFileSpec();

	CComPtr<IUnknown> pAppDomainSetupUnk;
	hr = pHost->CreateDomainSetup(&pAppDomainSetupUnk);
	if (FAILED(hr) || pAppDomainSetupUnk == NULL)
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_APPDOMAINSETUP, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return 0;
	}

	CComQIPtr<IAppDomainSetup> pAppDomainSetup = pAppDomainSetupUnk;

	hr = pAppDomainSetup->put_ApplicationBase(CComBSTR(xllDirectory));
	if (FAILED(hr))
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_APPLICATIONBASE, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return 0;
	}
	
	CComBSTR configFileName = addInFullPath;
	configFileName.Append(L".config");
	pAppDomainSetup->put_ConfigurationFile(configFileName);

	CComBSTR appDomainName = L"ExcelDna: ";
	appDomainName.Append(addInFullPath);
	pAppDomainSetup->put_ApplicationName(appDomainName);

	IUnknown *pAppDomainUnk = NULL;
	hr = pHost->CreateDomainEx(appDomainName, pAppDomainSetupUnk, 0, &pAppDomainUnk);
	if (FAILED(hr) || pAppDomainUnk == NULL)
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_APPDOMAIN, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return 0;
	}

	CComQIPtr<_AppDomain> pAppDomain(pAppDomainUnk);

	// Load plan for ExcelDna.Loader:
	// Try AppDomain.Load with the name ExcelDna.Loader.
	// Then if it does not work, we will try to load from a known resource in the .xll.

	CComPtr<_Assembly> pExcelDnaLoaderAssembly;
	hr = pAppDomain->Load_2(CComBSTR(L"ExcelDna.Loader"), &pExcelDnaLoaderAssembly);
	if (FAILED(hr) || pExcelDnaLoaderAssembly == NULL)
	{
		HRSRC hResInfoLoader = FindResource(hModuleCurrent, L"EXCELDNA_LOADER", L"ASSEMBLY");
		if (hResInfoLoader == NULL)
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_MISSINGEXCELDNALOADER, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return 0;
		}
		HGLOBAL hLoader = LoadResource(hModuleCurrent, hResInfoLoader);
		void* pLoader = LockResource(hLoader);
		ULONG sizeLoader = (ULONG)SizeofResource(hModuleCurrent, hResInfoLoader);
		
		CComSafeArray<BYTE> bytesLoader;
		bytesLoader.Add(sizeLoader, (byte*)pLoader);

		hr = pAppDomain->Load_3(bytesLoader, &pExcelDnaLoaderAssembly);
		if (FAILED(hr))
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_EXCELDNALOADER, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return 0;
		}

		CComBSTR pFullName;
		hr = pExcelDnaLoaderAssembly->get_FullName(&pFullName);
		if (FAILED(hr))
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_EXCELDNALOADERNAME, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return 0;
		}
	}
	
	CComPtr<_Type> pXlAddInType;
	hr = pExcelDnaLoaderAssembly->GetType_2(CComBSTR(L"ExcelDna.Loader.XlAddIn"), &pXlAddInType);
	if (FAILED(hr) || pXlAddInType == NULL)
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_XLADDIN, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return 0;
	}

	CComSafeArray<VARIANT> initArgs;
	initArgs.Add(CComVariant((INT32)pExportInfo));
	initArgs.Add(CComVariant((INT32)hModuleCurrent));
	initArgs.Add(CComVariant(addInFullPath.AllocSysString()));
	CComVariant initRetVal;
	CComVariant target;
	hr = pXlAddInType->InvokeMember_3(CComBSTR("Initialize"), (BindingFlags)(BindingFlags_Static | BindingFlags_Public | BindingFlags_InvokeMethod), NULL, target, initArgs, &initRetVal);
	if (FAILED(hr))
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_XLADDININIT, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return 0;
	}

	pHost_ForUnload = pHost.Detach();
	pAppDomain_ForUnload = (IUnknown*)pAppDomain.Detach();

	return initRetVal.boolVal == 0 ? false : true;
}