Setting Host Policy in appdomain
Due to popular demand, I am posting an example how to set host policy in appdomain.
(If you don't know what host policy is, please refer to the following two blogs:
Aspnet.Config
https://blogs.msdn.com/junfeng/archive/2004/10/07/239317.aspx
Assembly Binding Policy
https://blogs.gotdotnet.com/alanshi/commentview.aspx/d4edb084-c625-4b6e-8e5c-7c2580cfcee9)
The only way to set host policy is through CLR hosting API.
There are four CLR hosting APIs defined in mscoree.idl in .Net framework SDK.
#pragma midl_echo("STDAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, LPCWSTR pwszHostConfigFile, VOID* pReserved, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);")
#pragma midl_echo("STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);")
#pragma midl_echo("STDAPI CorBindToRuntimeByCfg(IStream* pCfgStream, DWORD reserved, DWORD startupFlags, REFCLSID rclsid,REFIID riid, LPVOID FAR* ppv);")
#pragma midl_echo("STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);")
The only one can set host policy is CorBindToRuntimeHost. The host policy is set automatically in every appdomain.
Documentation for CLR hosting interface can be found at https://www.gotdotnet.com/team/clr/HostingInterfaces.aspx.
The example below hosts CLR, then executes a managed application in default appdomain. The managed application simply loads an assembly to demostrate that host policy is applied.
E:\demo>more hostdemo.cpp
#include "windows.h"
#include "stdio.h"
#include "mscoree.h"
#import <mscorlib.tlb> raw_interfaces_only high_property_prefixes("_get","_put","_putref")
using namespace mscorlib;
int wmain(int argc, WCHAR **argv)
{
if (argc != 3) {
printf("Usage: HostDemo HostConfigFile AppToExecute\n");
return 1;
}
ICorRuntimeHost *pHost = NULL;
IUnknown *pAppDomainThunk = NULL;
_AppDomain *pAppDomain = NULL;
// let's host CLR
HRESULT hr = CorBindToRuntimeHost( L"v1.1.4322", // pwzVersion
L"wks", // pwzBuildFlavor
argv[1], // host config file
NULL, // reversed
0, // startup flag,
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(VOID**)&pHost);
if (FAILED(hr)) {
printf("CorBindToRuntimeHost failed with hr=0x%x.\n", hr);
return 2;
}
// Start the runtime
hr = pHost->Start();
if (FAILED(hr)) {
printf("ICorRuntimeHost->Start failed with hr=0x%x.\n", hr);
return 3;
}
// Get the default appdomain.
hr = pHost->GetDefaultDomain(&pAppDomainThunk);
if (FAILED(hr)) {
printf("ICorRuntimeHost->GetDefaultDomain failed with hr=0x%x.\n", hr);
return 4;
}
// Get System::_AppDomain interface
hr = pAppDomainThunk->QueryInterface(__uuidof(_AppDomain),
(void**) &pAppDomain);
if (FAILED(hr)) {
printf("Can't get System::_AppDomain interface\n");
return 5;
}
long lRet= 0;
// call System::_AppDomain::ExecuteAssembly(String)
hr = pAppDomain->ExecuteAssembly_2(_bstr_t(argv[2]), &lRet);
if (FAILED(hr)) {
printf("_AppDomain::ExecuteAssembly_2 failed with hr=0x%x.\n", hr);
return 6;
}
return 0;
}
E:\demo>more hello.cs
using System;
using System.Reflection;
public class test
{
public static void Main()
{
Console.WriteLine(Assembly.Load("test, version=1.0.0.0, culture=neutral, publickeytoken=ba6def5dd8a8ddac").Location);
}
}
E:\demo>more test.cs
using System;
using System.Reflection;
[assembly:AssemblyKeyFile("1.snk")]
public class test
{
public String WhoAmI()
{
return "Test.dll";
}
}
E:\demo>more build.bat
cl hostdemo.cpp mscoree.lib
csc hello.cs
csc /t:library test.cs
move test.dll c:\temp\test.dll
E:\demo>more example.config
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="test"
publicKeyToken="ba6def5dd8a8ddac"
culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="0.0.0.0"/>
<codeBase version="0.0.0.0" href="c:\temp\test.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
E:\demo>build.bat
E:\demo>cl hostdemo.cpp mscoree.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.
hostdemo.cpp
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.
/out:hostdemo.exe
hostdemo.obj
mscoree.lib
E:\demo>csc hello.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
E:\demo>csc /t:library test.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
E:\demo>move test.dll c:\temp\test.dll
1 file(s) moved.
E:\demo>hostdemo example.config hello.exe
c:\temp\test.dll
Due to the restriction of codebase in host policy, I have to use a bogus redirect in example.config to make sure the codebase is picked up correctly.
The example is compiled with VS.Net 2003, and run under .Net framework 1.1.