2011-01-20 56 views
0

我有一个名为Foo的C#.NET库,它生成一个Foo.dll文件。这也是通过一个config文件看起来像这样配置:从非托管C++配置.NET库

<?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> 

我想要做的就是通话功能在这个.NET库从非托管C++程序调用的酒吧,并能够从更改其配置非托管C++应用程序。我可以通过在Foo中将类/接口属性ComVisible设置为true来从Bar调用Foo函数。但是,我无法从非托管C++应用程序更改.config文件值 - 服务器始终是“localhost”

是我想要做的 - 从非托管C++配置.NET库 - 甚至可能吗?

回答

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

0

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

您需要找到不同的方法。

编辑:您也可以创建一个形式为HostApp.exe.config的配置文件,其中HostApp是您的本机EXE的完整路径。

+0

与此相反,dll确实有配置文件。例如,如果上例中给出的.NET库的使用者从非托管C++ exe更改为托管C#exe,则可以通过复制来更新共享库Foo.dll的Server。将Foo的值配置到Bar.exe.config中。因此,我的原始问题是:如果.NET消费者有可能更新.NET dll的配置文件,那么非托管C++使用者是否可以更新.NET dll的配置文件? – 2011-01-20 22:23:19

+0

@GP:这是一个** EXE **的配置文件。 DLL本身没有配置文件。 .Net框架将从不**看`Foo.dll.config`。 – SLaks 2011-01-20 22:49:22