C++ 非托管 程序调用托管程序

本文介绍了一个C++原生控制台应用程序示例,该程序通过查询注册表来验证特定版本的.NET Framework是否已安装,并加载指定版本的公共语言运行时(CLR)。接着,它使用mscorlib库中的接口和方法来加载程序集和类型并执行方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

This is a sample native console application which will query the registry to verify if a specific version of the .NET Framework is installed. It will then use the CorBindToRuntimeEx API to load a specific version of the Common Language Runtime (CLR). Finally, it uses the Interfaces and methods exposed in mscorlib.tlb to load an assembly and type and execute methods.

Create a new C++ Console application named CheckCLR and replace the code in CheckCLR.cpp with the following code:

/*
    CheckCLR.cpp - A Native Code CLR Host Sample

    CheckCLR is a native console application which queries the registry to
    determine if a specific version of the .NET runtime is installed on the
    machine. It then loads the specific CLR required.

    It will then load a managed console app and execute the Main method.
    It then loads a managed assembly and executes a method.
*/
#include "stdafx.h"
#include <windows.h>
#include <mscoree.h>
#include <assert.h>
#include <stdio.h>
#include <tchar.h>

// Import mscorlib typelib. Using 1.0 for maximum backwards compatibility
#import "C:\windows\Microsoft.NET\Framework\v1.0.3705\mscorlib.tlb" auto_rename
// Link with mscoree.dll import lib.
#pragma comment(lib,"mscoree.lib")

using namespace mscorlib;

int _tmain(int argc, _TCHAR* argv[])
{
    //
    // Query 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\Install' DWORD value
    // See http://support.microsoft.com/kb/318785/ (http://support.microsoft.com/kb/318785/) for more information on .NET runtime versioning information
    //
    HKEY key = NULL;
    DWORD lastError = 0;
    lastError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5"),0,KEY_QUERY_VALUE,&key);
    if(lastError!=ERROR_SUCCESS) {
        _putts(TEXT("Error opening HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5"));
        return 1;
    }

    DWORD type;
    BYTE data[4];
    DWORD len = sizeof(data);
    lastError = RegQueryValueEx(key,TEXT("Install"),NULL,&type,data,&len);
 
    if(lastError!=ERROR_SUCCESS) {
        RegCloseKey(key);
        _putts(TEXT("Error querying HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5\\Install"));
        return 2;
    }

    RegCloseKey(key);

    // Was Install DWORD key value == 1 ??
    if(data[0]==1)
        _putts(TEXT(".NET Framework 3.5 is installed"));
    else {
        _putts(TEXT(".NET Framework 3.5 is NOT installed"));
        return 3;
    }

    // 
    // Load the runtime the 3.5 Runtime (CLR version 2.0)
    //
    LPWSTR pszVer = L"v2.0.50727";  // .NET Fx 3.5 needs CLR 2.0
    LPWSTR pszFlavor = L"wks";
    ICorRuntimeHost *pHost = NULL;

    HRESULT hr = CorBindToRuntimeEx( pszVer,       
                                                       pszFlavor,    
                                                       STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC, 
                                                       CLSID_CorRuntimeHost, 
                                                       IID_ICorRuntimeHost,
                                                       (void **)&pHost);

    if (!SUCCEEDED(hr)) {
        _tprintf(TEXT("CorBindToRuntimeEx failed 0x%x\n"),hr);
        return 1;
    }
 
    _putts(TEXT("Loaded version 2.0.50727 of the CLR\n"));
 
    pHost->Start(); // Start the CLR

    //
    // Get a pointer to the default domain in the CLR
    //
    _AppDomainPtr pDefaultDomain = NULL;
    IUnknownPtr   pAppDomainPunk = NULL;

    hr = pHost->GetDefaultDomain(&pAppDomainPunk);
    assert(pAppDomainPunk); 
 
    hr = pAppDomainPunk->QueryInterface(__uuidof(_AppDomain),(void**) &pDefaultDomain);
    assert(pDefaultDomain);

    //
    // Load an Exe Assembly and call Main()
    //
    _bstr_t bstrExeName = L"ConsoleApplication1.exe";
    try {
        hr = pDefaultDomain->ExecuteAssembly_2(bstrExeName);
    }
    catch(_com_error& error) {
        _tprintf(TEXT("ERROR: %s\n"),(_TCHAR*)error.Description());
        goto exit;
    }

    /*
        Load a type from a DLL Assembly and call it

        Doing the same thing from native code as this C# code:

            System.Runtime.Remoting.ObjectHandle objptr;
            objptr = AppDomain.CurrentDomain.CreateInstanceFrom("ClassLibrary1.dll",
                                                                                           "ClassLibrary1.Class1");
            object obj = objptr.Unwrap();
            Type t = obj.GetType();
            t.InvokeMember("Test",
                                   BindingFlags.InvokeMethod,
                                   null,
                                   obj,
                                   new object[0]);
    */
    try {
        _ObjectHandlePtr pObjectHandle; 
        _ObjectPtr pObject; 
        _TypePtr pType;
        SAFEARRAY* psa;

        // Create an instance of a type from an assembly
        pObjectHandle = pDefaultDomain->CreateInstanceFrom(L"ClassLibrary1.dll",     // no path -- local directory
                                                                                      L"ClassLibrary1.Class1");
  
        variant_t vtobj = pObjectHandle->Unwrap();                                     // Get an _Object (as variant) from the _ObjectHandle
        vtobj.pdispVal->QueryInterface(__uuidof(_Object),(void**)&pObject);  // QI the variant for the Object iface
        pType = pObject->GetType();                                                         // Get the _Type iface
        psa = SafeArrayCreateVector(VT_VARIANT,0,0);                                // Create a safearray (0 length)
        pType->InvokeMember_3("Test",                                                     // Invoke "Test" method on pType
                                            BindingFlags_InvokeMethod,
                                            NULL,
                                            vtobj,
                                            psa );
        SafeArrayDestroy(psa);                                                                   // Destroy safearray
    }
    catch(_com_error& error) {
        _tprintf(TEXT("ERROR: %s\n"),(_TCHAR*)error.Description());
        goto exit;
    }

exit:
    pHost->Stop();
    pHost->Release();

    return 0;
}

/*** End of file CheckCLR.cpp ***/

Create a C# Console Application named ConsoleApplication1. Add a Console.WriteLine call in the Main method and output a simple string message. Build ConsoleApplication1. Copy the ConsoleApplication1.exe build target to the ouput directory where CheckCLR.exe is built. Alternatively, you can change the code above to have the full path name to where ConsoleApplication1.exe is built.

Create a C# Class Library named ClassLibrary1. In the Class1 class, add a public method named Test. In Test, add a Console.WriteLine call and output a simple string message. Build ClassLibrary1.dll. Copy the ClassLibrary1.dll build target to the outut directory where CheckCLR.exe is built. Alternatively, you can change the code above to have the full path name to where ClassLibrary1.dll is built.

After building CheckCLR, you should should be able to run CheckCLR.exe from a command prompt and see the output of the Console.WriteLine calls:

    .NET Framework 3.5 is installed
    Loaded version 2.0.50727 of the CLR


    Hello World from ConsoleApplication1.Main
    Hello World from ClassLibrary1.Class1


If running CheckCLR.exe under the debugger from your Visual C++ project, you may get could not load file or assembly error messages. In that case, copy ConsoleApplication1.exe and ClassLibrary1.dll to the folder containing the CheckCLR.sln solution file. The debugger uses that folder as the application default directory.

转载于:https://www.cnblogs.com/sea918/archive/2010/01/26/1656646.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值