2011-01-20 57 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