从非托管C ++配置.NET库

时间:2011-01-20 19:39:41

标签: c# c++ com configuration unmanaged

我有一个名为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库 - 甚至可能吗?

2 个答案:

答案 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版本以外的任何东西,所以我从不打扰升级任何托管代码。

另见:Hosting Overview

答案 1 :(得分:0)

.Net配置系统为EXE加载.config个文件; DLL没有配置文件。

您需要找到不同的方法。

编辑:您还可以创建HostApp.exe.config形式的配置文件,其中HostApp是您原生EXE的完整路径。