无法使用 /clr 选项从 Visual C++ 项目加载 CLR

Posted

技术标签:

【中文标题】无法使用 /clr 选项从 Visual C++ 项目加载 CLR【英文标题】:Unable load CLR from Visual C++ project with /clr option 【发布时间】:2015-08-06 11:16:53 【问题描述】:

我正在尝试使用以下配置创建 Visual C++ Win32 控制台应用程序: 操作系统:Windows 7 视觉工作室:VS 2012 公共语言运行时支持:公共语言运行时支持(/clr[Project Properties].

我还创建了一个 Visual C# WPF 应用程序并使用该 dll 从下面提到的 c++ 程序中使用它。

我遵循此链接中的所有说明:https://code.msdn.microsoft.com/CppHostCLR-e6581ee0

问题是我无法启动 CLR,即 ICLRRunTimeHost:Start 方法返回 0x1 而不是 0x0。请帮助/指导我解决我的错误,如果我的代码在概念上是错误的,请指导我。

请在下面找到我粘贴的代码:

#include "stdafx.h"
#include <metahost.h>
#include <mscoree.h> 
//#include <Windows.h>

//#using <WpfWithoutService.dll>
//using namespace System;
//using namespace System::Threading;

//using namespace WpfWithoutService;

#pragma comment(lib, "mscoree.lib")
/*ref class MainWinClass

public:
    void MainForm()
    
        MainWindow^ mainwin = gcnew MainWindow();
        //mainwin->Activate();
        //mainwin->InitializeComponent();
    
;*/

int _tmain(int argc, _TCHAR* argv[])

    HRESULT hr; 
    //BOOL fLoadable;

    ICLRMetaHost *pMetaHost = NULL;
    LPCWSTR pwzVersion = (LPCWSTR)"v4.0.30319";


    //hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); 
    hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
    if (FAILED(hr)) 
     
        wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr); 
    

    ICLRRuntimeInfo *pRuntimeInfo = NULL; 
// Get the ICLRRuntimeInfo corresponding to a particular CLR version.
    //hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID *)&pRuntimeInfo); 
    hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)); 
    if (FAILED(hr)) 
     
        wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr); 
        //goto Cleanup; 
     


/*Check if the specified runtime can be loaded into the process. This  
// method will take into account other runtimes that may already be  
// loaded into the process and set pbLoadable to TRUE if this runtime can  
// be loaded in an in-process side-by-side fashion.  

    hr = pRuntimeInfo->IsLoadable(&fLoadable); 
    if (FAILED(hr)) 
     
        wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr); 
        //goto Cleanup; 
     


    if (!fLoadable) 
     
        wprintf(L".NET runtime %s cannot be loaded\n", "4.0.30319.18063"); 
        //goto Cleanup; 
    */


// Load the CLR into the current process and return a runtime interface  pointer. 
    ICLRRuntimeHost *pClrRuntimeHost = NULL;
    hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost)); 
    if (FAILED(hr)) 
     
        wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr); 
    


// Start the CLR.
    if (hr == S_OK)
    
        hr = pClrRuntimeHost->Start(); 
        if (FAILED(hr)) 
         
            wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr); 
            //goto Cleanup; 
        
    

//Load an assembly and call the required function
    if (hr == S_OK) // if CLR is started successfully
    
        DWORD dwRet;
        hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(L"WpfWithoutService.dll", L"WpfWithoutService.MainWindow", L"InitializeComponent", NULL, &dwRet); 
        if (FAILED(hr)) 
         
            wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr); 
         
    


    if (pMetaHost) 
     
        pMetaHost->Release(); 
        pMetaHost = NULL; 
     
    if (pRuntimeInfo) 
     
        pRuntimeInfo->Release(); 
        pRuntimeInfo = NULL; 
     
    if (pClrRuntimeHost) 
     
        // Please note that after a call to Stop, the CLR cannot be  
        // reinitialized into the same process. This step is usually not  
        // necessary. You can leave the .NET runtime loaded in your process. 
        //wprintf(L"Stop the .NET runtime\n"); 

            pClrRuntimeHost->Stop()
            pClrRuntimeHost->Release(); 
            pClrRuntimeHost = NULL; 

     


    return 0;

【问题讨论】:

我没有看到任何 Visual C++ 代码。您正在使用本机 C++ 并以某种方式尝试手动加载 CLR..??为什么不直接创建托管 C++ 控制台应用程序? 【参考方案1】:

ICLRRunTimeHost:Start 方法返回 0x1 而不是 0x0

即 S_FALSE,在 CLR 已经运行时返回。你不能启动它两次。

使用以下配置...公共语言运行时支持

这是不合适的,它强制 CLR 在代码开始运行之前加载和初始化。您只能在使用 /clr 构建的本机 C++ 程序中编写这样的 CLR 托管代码。

或者换句话说,您根本不需要编写此代码。并且没有明显的理由让您想要从 sn-p 中获取。您可以使用反射实现完全相同的效果,从 Assembly::Load() 开始。或者更简单,通过添加对该程序集的引用。实际意图很难逆向工程。如果确实有,那么只需将 /clr 选项设置回“否”。

【讨论】:

感谢 Hans Passant 的回复,它解决了我的第一个问题。现在至少我能够加载 clr 并启动它。向前移动新问题出现了,在调用 ExecuteInDefaultAppDomain 函数时它返回 Missing Function 错误。 hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(L"D:\\IPTCom\\WPFApp\\WpfApplication_mine\\WpfApplication_mine\\bin\\Debug\\WpfApplication_mine.exe", L"WpfApplication_mine.App", L"Main",L" ", &dwRet);....请您帮助/指导我解决此错误。

以上是关于无法使用 /clr 选项从 Visual C++ 项目加载 CLR的主要内容,如果未能解决你的问题,请参考以下文章

C 文件无法在 c++ Visual Studio 中编译

是否在CLR上运行非托管Visual C ++?

在 Visual Studio 2012 中编译启用 CLR 的 C++ 项目时出现 C2248 错误

Visual C++ CLR 设计器在第二次运行项目和编辑设计时总是显示 0x8000000A 错误

Visual Studio 2019 缺少 SQL CLR VB

在 Visual C++ 中使用 ^ 运算符