我有一个名为Foo的C#.NET库,它生成一个Foo.dll文件。它也可以通过.config文件进行配置,如下所示:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Foo.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</sectionGroup>
</configSections>
<applicationSettings>
<Foo.Properties.Settings>
<setting name="Server" serializeAs="String">
<value>localhost</value>
</setting>
</Foo.Properties.Settings>
</applicationSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
我想要做的是从一个名为Bar的非托管C ++程序调用此.NET库中的函数,并能够从非托管C ++应用程序更改其配置。通过在Foo中将类/接口属性ComVisible设置为true,我能够从Bar调用Foo函数。但是,我无法从非托管C ++应用程序更改.config文件值 - 服务器始终是“localhost”。
我正在尝试做什么 - 从非托管C ++配置.NET库 - 甚至可能吗?
答案 0 :(得分:4)
这是可能的,但不是少量的工作。通常更容易创建appdomain并从托管世界设置配置,然后在托管代码中创建一个小的“thunking”层,以便为非托管客户端包装它。但既然这不是你要求的,那么你就可以实现目标:
首先,您需要导入mscorelib:
#include <mscoree.h>
#import <mscorlib.tlb> raw_interfaces_only no_smart_pointers high_property_prefixes("_get","_put","_putref")
然后绑定到运行时:
ICorRuntimeHost runtimeHost;
hr = CorBindToRuntimeEx(
NULL, //Retrieve latest version by default
L"wks", //Request a WorkStation build of the CLR
STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC,
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(void**)&runtimeHost
);
现在启动CLR并创建一个AppDomainSetup实例。
hr = runtimeHost->Start();
IAppDomainSetup pSetup;
hr = runtimeHost->CreateDomainSetup(&pSetup);
现在根据需要填写设置信息:
hr = pSetup->put_ApplicationBase(_bstr_t(thisFile));
hr = pSetup->put_ConfigurationFile(_bstr_t(configFile));
最后创建域名:
hr = __gRuntimeHost->CreateDomainEx(L"ISAPI.Net", pSetup, NULL, &pDomain);
现在,您可以选择实例化对象并调用方法:
hr = pDomain->CreateInstanceFrom(_bstr_t(assemblyFile), _bstr_t("Namespace.ClassName"), &pObjectHandle);
VARIANT vtUnwrapped;
hr = spObjectHandle->Unwrap(&vtUnwrapped);
IDispatch pDisp = vtUnwrapped.pdispVal;
DISPID dispid;
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
hr = pDisp->GetIDsOfNames (
IID_NULL,
szMemberName,
1,
LOCALE_SYSTEM_DEFAULT,
&dispid
);
hr = pDisp->Invoke (
dispid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&dispparamsNoArgs,
NULL,
NULL,
NULL
);
显然上面的代码片段是不完整的;但是,如果您对C ++ COM足够熟练,那么上面应该为您提供足够的信息来解决它。您应该注意,这是'旧'(1.x)托管接口,我可以证明继续通过3.5,我不知道如何/如果这些在4.0上工作。自.Net 2.0 new hosting interfaces起介绍。我从来没有需要除1.x版本以外的任何东西,所以我从不打扰升级任何托管代码。
答案 1 :(得分:0)
.Net配置系统为EXE加载.config
个文件; DLL没有配置文件。
您需要找到不同的方法。
编辑:您还可以创建HostApp.exe.config
形式的配置文件,其中HostApp
是您原生EXE的完整路径。