问题描述
限时送ChatGPT账号..假设我已经
一个名为managed.dll
的 C# DLL,它是 COM 可见的.一个名为 magaged.exe
的 C# EXE,它使用 managed.dll
并且有一个名为 managed.exe.config
的 app.config.一个名为 unmanaged.exe
的 C++ EXE,它通过 COM 调用 managed.dll
并具有与 C# EXE 相同的 app.config 但称为 unmanaged.exe.config
在这种情况下.
a C# DLL calledmanaged.dll
which is COM visible. a C# EXE calledmagaged.exe
which uses themanaged.dll
and which has an app.config calledmanaged.exe.config
. a C++ EXE calledunmanaged.exe
which calls themanaged.dll
over COM and which has the same app.config as the C# EXE but calledunmanaged.exe.config
in this case.
managed.dll
有以下两个测试属性:
The managed.dll
has the following two test properties:
public bool IsServerGC
{
get { return System.Runtime.GCSettings.IsServerGC; }
}
public bool AreVeryLargeObjectsAllowed
{
get
{
try
{
long l = 20000;
double[,] d = new double[l, l];
return l * l == d.LongLength;
}
catch { return false; }
}
}
两个 EXE 的 app.config
看起来都是这样:
The app.config
looks like that for both EXEs:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
<!--<gcConcurrent enabled="false"/>-->
<gcServer enabled="true"/>
</runtime>
</configuration>
对于 managed.exe
一切正常.但是对于 unmanaged.exe
,<gcServer enabled="true"/>
设置被忽略.我不明白为什么?
For the managed.exe
everything works as expected. But for the unmanaged.exe
the <gcServer enabled="true"/>
setting is ignored. I cannot understand why?
我可以看到在创建 COM 对象的第一个实例时加载了 unmanaged.exe.config
.它也被使用,通过更改例如 <gcAllowVeryLargeObjects enabled="true"/>
设置进行测试.
I can see that the unmanaged.exe.config
is loaded when the first instance of a COM object is created. It's as well used, tested by changing for example the <gcAllowVeryLargeObjects enabled="true" />
setting.
我使用的是 Visual Studio 2013、Windows 7(64 位)和 .NET 4.6.1.一切都是为 x64 编译的.
I'm using Visual Studio 2013, Windows 7 (64-bit) and .NET 4.6.1. Everything is compiled for x64.
在 COM 上使用 managed.dll
时,为什么会忽略 <gcServer enabled="true"/>
设置?
Any ideas why the <gcServer enabled="true"/>
setting is ignored when the managed.dll
is used over COM?
问候沃尔米希
推荐答案
我找到了两种不同的解决方法:
I was able to find two different workarounds:
解决方法 1(COM 互操作之前的主机 CLR)
Workaround 1 (Host CLR before COM Interop)
我必须更改以下内容:
名为unmanaged.exe
的 C++ EXE 必须先托管 CLR 并设置启动标志,然后才能通过 COM 调用 managed.dll
.
the C++ EXE calledunmanaged.exe
has to host the CLR first and set the startup flags before calling themanaged.dll
over COM.
unmanaged.exe
的源文件如下所示:
#include "stdafx.h"
#include <metahost.h>
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")
#import "..\managed\bin\Release\managed.tlb"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// Init .NET
ICLRMetaHost *pMetaHost = nullptr;
ICLRRuntimeInfo *pRuntimeInfo = nullptr;
HRESULT hr;
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
hr = pRuntimeInfo->SetDefaultStartupFlags(STARTUP_SERVER_GC, NULL);
// Init COM
hr = CoInitialize(NULL);
IManagedTestClassPtr pManagedTestClass(__uuidof(ManagedTestClass));
// and so on ...
// End COM
CoUninitialize();
// END .NET
if (pMetaHost)
{
pMetaHost->Release();
pMetaHost = NULL;
}
if (pRuntimeInfo)
{
pRuntimeInfo->Release();
pRuntimeInfo = NULL;
}
return 0;
}
这是我个人首选的解决方法,因为不需要额外的 helper.dll.
This is my personal preferred workaround, because no additional helper.dll is needed.
解决方法 2(在 COM 互操作之前使用 C++/CLI DLL)
Workaround 2 (Use C++/CLI DLL before COM Interop)
我必须更改以下内容:
添加一个名为helper.dll
的 C++/CLI DLL,它有一个名为 helper.dll.config
的 app.config.app.config 与 C++ EXE 相同.名为unmanaged.exe
的C++ EXE 必须先从C++/CLI helper.dll
调用一个函数,然后再调用managed.dll
> 通过 COM.
add a C++/CLI DLL calledhelper.dll
which has an app.config calledhelper.dll.config
. The app.config is the same as for the C++ EXE. the C++ EXE calledunmanaged.exe
has to call first a function from the C++/CLIhelper.dll
before calling themanaged.dll
over COM.
helper.dll
具有以下头文件:
#pragma once
#ifdef TEST_HELPER_EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#pragma comment (lib, "..\\x64\\Release\\helper.lib") // if importing, link also
#endif
DLLAPI int IsServerGC();
以及以下源文件:
#include "stdafx.h"
#define TEST_HELPER_EXPORTS
#include "helper.h"
int IsServerGC()
{
return System::Runtime::GCSettings::IsServerGC ? 1 : 0;
}
unmanaged.exe
的源文件如下所示:
#include "stdafx.h"
#include "..\helper\helper.h"
#import "..\managed\bin\Release\managed.tlb"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int isServerGC = IsServerGC(); // Init .NET with the C++/CLI helper.dll
HRESULT hr = CoInitialize(NULL); // Init COM
IManagedTestClassPtr pManagedTestClass(__uuidof(ManagedTestClass));
// and so on ...
}
如果 helper.dll.config
文件丢失,<gcServer enabled="true"/>
设置将再次被忽略.其他设置,例如 <gcAllowVeryLargeObjects enabled="true"/>
设置,在 unmanaged.exe.config
文件中定义.
If the helper.dll.config
file is missing the <gcServer enabled="true"/>
setting is ignored again. The other settings, for example the <gcAllowVeryLargeObjects enabled="true" />
setting, are defined in the unmanaged.exe.config
file.
对我来说,当我不使用 CLR 托管或解决方法 helper.dll 时,为什么会忽略
先?<gcServer enabled="true"/>
设置仍然不清楚
For me it's still not clear why the <gcServer enabled="true"/>
setting is ignored when I'm not using the CLR hosting or the workaround helper.dll
first?
问候沃尔米希
这篇关于带有 gcServer = true 和 gcAllowVeryLargeObjects = true 的 C# COM DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论