Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
确定何时将.NET加载到(非托管)C++;_.net_C++ - Fatal编程技术网

确定何时将.NET加载到(非托管)C++;

确定何时将.NET加载到(非托管)C++;,.net,c++,.net,C++,[这是TLDR…抱歉…] 我在一个巨大的(大部分)C++/MFC应用程序上工作,其中包含数百个DLL;它支持通过COM动态加载的“外接程序”机制,因此可以使用COM互操作在.NET中开发外接程序。在.NET w/o中使用这种“外接程序”机制开发了一些有限的新功能(尽管仍然是动态加载的);但是,最终用户可以决定不使用此功能。因此,.NET可能不会在启动时加载 但是,当加载.NET时,我需要进行一些特定于.NET的初始化(特别是设置CurrentUICulture以匹配本机/非托管UI) 一种解决方

[这是TLDR…抱歉…]

我在一个巨大的(大部分)C++/MFC应用程序上工作,其中包含数百个DLL;它支持通过COM动态加载的“外接程序”机制,因此可以使用COM互操作在.NET中开发外接程序。在.NET w/o中使用这种“外接程序”机制开发了一些有限的新功能(尽管仍然是动态加载的);但是,最终用户可以决定不使用此功能。因此,.NET可能不会在启动时加载

但是,当加载.NET时,我需要进行一些特定于.NET的初始化(特别是设置CurrentUICulture以匹配本机/非托管UI)

一种解决方案是,当代码开始加载新的.NET功能或COM加载项时,简单地punt并进行.NET初始化。鉴于此应用程序的性质,它可能是一个95%以上的解决方案(大多数用户将使用新功能)

但这不是万无一失的。有人可以通过构建带有/clr标志的模块“随时”添加新的.NET功能(请记住,这是一个巨大的应用程序)

另一个更健壮(且显而易见)的解决方案是,只需在启动时通过C++/CLI加载.NET即可。但是有些死板的C++开发人员,每个字节和时钟周期都不想这样做;有些可以理解,因为除非加载.NET,否则不需要设置CurrentUICulture

我想到的另一种可能性是钩住
LoadLibrary
并查找mscorlib。现在我知道.NET由于某种原因即将加载,请以正常方式加载它,并在其他代码执行任何操作之前进行初始化。但是挂钩
LoadLibrary
(或者其他任何东西,就这一点而言)真的不是我想做的事情

那么,有没有一种简单(更简单)/更好的方法来判断.NET是否即将加载

编辑:里德对洛克版本的回答非常接近。唯一的问题是,如果在混合模式DLL/程序集中链接,它将无法工作

// ClrAboutToLoad.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <MSCorEE.h>

// http://community.bartdesmet.net/blogs/bart/archive/2005/07/22/2882.aspx
FLockClrVersionCallback begin_init, end_init;
STDAPI hostCallback()
{
    printf("hostCallback()\n");

    // we're in control; notify the shim to grant us the exclusive initialization right
    begin_init();

    ICLRRuntimeHost *pHost = NULL;
    HRESULT hr = CorBindToRuntimeEx(NULL, L"wks", STARTUP_SERVER_GC, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*) &pHost);
    hr = pHost->Start();

    // mission completed; tell the shim we're ready
    end_init();

    return S_OK;
}

int _tmain(int argc, _TCHAR* argv[])
{
    LockClrVersion(&hostCallback, &begin_init, &end_init);

    //fnTheDLL();
    HMODULE hModule = LoadLibrary(L"TheDLL");
    FARPROC fp = GetProcAddress(hModule, "fnTheDLL");
    typedef void (*fnTheDLL_t)();
    fnTheDLL_t fnTheDLL = reinterpret_cast<fnTheDLL_t>(fp);
    fnTheDLL();
    FreeLibrary(hModule);

    return 0;
}
//ClrAboutToLoad.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
// http://community.bartdesmet.net/blogs/bart/archive/2005/07/22/2882.aspx
FLockClrVersionCallback开始初始化,结束初始化;
STDAPI hostCallback()
{
printf(“hostCallback()\n”);
//我们在控制中;通知垫片授予我们独占初始化权
begin_init();
ICLRRuntimeHost*pHost=NULL;
HRESULT hr=CorBindToRuntimeEx(NULL,L“wks”、启动服务器\U GC、CLSID\U CLRUNTIMEOST、IID\U ICLRRUNTIMEOST(PVOID*)和PHOT);
hr=pHost->Start();
//任务完成;告诉垫片我们准备好了
end_init();
返回S_OK;
}
int _tmain(int argc,_TCHAR*argv[]
{
LockClrVersion(&hostCallback,&begin\u init,&end\u init);
//fnthedl();
HMODULE HMODULE=加载库(L“thedell”);
FARPROC fp=GetProcAddress(hModule,“fntheddll”);
typedef void(*fnTheDLL_t)();
fntheddll\u t fntheddll=重新解释铸件(fp);
fnthedl();
免费图书馆(hModule);
返回0;
}

您可能应该在应用程序启动时初始化.NET framework。我在类似的背景下开发应用程序,它偶尔会死锁,因为两个DLL同时试图通过间接访问.net DLL来初始化.net framework。为了解决这个问题,我们在可执行文件入口点的前几行中调用了


我认为操作系统没有办法告诉你是否要加载.NET。

你可以。然后,您可以对加载哪个版本的运行时(1.1?2.0?4.0?)做出更具体的决定,并将托管代码与代码分开。因此,有两件事可能会对您有所帮助:性能计数器和WMI。NET CLR与两者都集成,您应该能够与其中任何一个进行交互(WMI可能是最好的),以监视AppDomain的启动。然而,这两种工具都不是特别理想的,就开销而言,按照盛江的建议,自己托管CLR可能会更有效率(从而让您的“字节计数器”更满意)

另一方面,如果您对开发团队有任何影响和控制措施,我会稍微控制一下“字节计数器”。关于.NET的最大误解之一是它比C++效率低。旧的谬误需要被掩埋,因为.NET可以令人惊讶地高效,并且当它被正确使用时,比C++更有效。除了这两个平台的基准效率之外,您还必须问这样一个问题:如果我花费未知的时间优化最细的粒度,而从统计上看,它的更大规模通常会破坏性能:跨进程调用,那么我将真正获得多少效率(即从C++调用COM对象,从.NET调用.NET对象),调用远程进程(即Web服务、RPC等),调用数据库,等等。
您可以尝试解决.NET AppDomain启动问题,以消除字节计数器的误解,也可以正确地实现.NET系统,并避免封送和操作间碰撞,这将比任何字节级性能调整都要耗费大量精力。

而不是在程序集已加载,是否可以在加载AppDomain时挂接?请查看System.AppDomainManager以执行此操作


在GAC中加载子类System.AppDomainManager后,只需设置一些环境变量(APPDOMAIN\u MANAGER\u类型、APPDOMAIN\u MANAGER\u ASM)运行C++程序之前,

< p>我相信你可以通过使用任何托管API之前的进程调用非托管函数来实现这一点。这个函数允许你指定两种方法。 第一个方法(pBeginHostSetup)是在为托管进程初始化CLR之前调用的