从 Visual C# 2019 创建的 DLL 可以在 MFC 6.0 中使用吗?
Posted
技术标签:
【中文标题】从 Visual C# 2019 创建的 DLL 可以在 MFC 6.0 中使用吗?【英文标题】:Can a DLL created from Visual C# 2019 be used in MFC 6.0? 【发布时间】:2021-03-16 04:21:37 【问题描述】:我使用 Visual C# 2019 (.NET Framework) 编写了一个简单的 Web 服务获取函数并将其编译为 DLL。
namespace Transporter
public class transport
private Int32 returnCode;
private string responseBody;
private HttpClient client = new HttpClient();
public Int32 StartRequest(string baseAddress, string content, string token, string userName, string password)
var t = Task.Run(() => postRequest(baseAddress, content, token, userName, password));
t.Wait();
responseBody = t.Result;
return returnCode;
private async Task<string> postRequest(string baseAddress, string content, string token, string userName, string password)
try
using (var client = new HttpClient())
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Token", token);
client.DefaultRequestHeaders.Add("username", userName);
client.DefaultRequestHeaders.Add("password", password);
returnCode = 0;
responseBody = "";
using (HttpResponseMessage response = await client.PostAsJsonAsync(baseAddress, content))
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
catch (Exception ex)
returnCode = 99;
return ex.ToString();
我想在使用 MFC 6.0 编写的应用程序中使用 DLL。我尝试了 dllimport 和 loadlibrary,但没有成功。
typedef int32 (CALLBACK* LPSTARTREQUEST)(CString, CString, CString, CString, CString);
HINSTANCE hinstDLL; // Handle to DLL
LPSTARTREQUEST lpStartRequest; // Function pointer
int32 intReturnCode; // Return code from DLL function
CString cstrBaseAddress, cstrContent, cstrToken, cstrUserName, cstrPassword;
hinstDLL = LoadLibrary("Transporter.dll");
if (hinstDLL != NULL)
lpStartRequest = (LPSTARTREQUEST)GetProcAddress(hinstDLL, "StartRequest");
if (!lpStartRequest)
// handle the error
return "error";
else
// call the function
intReturnCode = lpStartRequest(cstrBaseAddress, cstrContent, cstrToken, cstrUserName, cstrPassword);
FreeLibrary(hinstDLL);
谁能告诉我这是否真的可行? 谢谢。
【问题讨论】:
“Visual C# 2019”告诉我们的比你想象的要少。 DLL 是 .NET Framework、.NET Standard 还是 .NET Core / .NET 5? MFC 和 VC++ 6 除外,从问题中不清楚如何使用来自 any 非托管的“dllimport and loadlibrary”的 C# 程序集C++ 应用程序,甚至是使用相同的 VS 2019 创建的应用程序。 @Llama 使用 .NET Framework 4.7.2 @Ives 打开developer command prompt 并运行dumpbin /exports Transporter.dll
。你看到那里列出了StartRequest
吗?如果没有,那么无论您在哪个版本的 VC++ 中编写非托管代码,都没有可以调用的导出。如果您确实看到它,则显示相关的 C# 代码,因为导出纯.NET 本身不支持 C API。
用 C# 编写的函数完全不可能按值接受 CString
类型的参数。这就是忽略,CString
甚至不是一个类型,而是一个宏。
【参考方案1】:
您不能直接从 MFC 代码调用 C# 类库中的 .NET 函数。您需要使用 COM 而不是 win32 提供的 DLL 管理功能。例如。插入LoadLibrary()
,您将使用COM 的IDispatch::QueryInterface()
,而不是GetProcAddress()
,您将调用IDispatch::GetIDsOfNames()
来检索函数的入口点,然后您将使用IDispatch::Invoke()
调用它。
在这样做之前有一些必要的准备工作:
在您的 .NET 类库中,在项目属性的构建选项卡上打开“注册 COM 互操作性”。 此外,建议在属性中“签署程序集”。如果您想为类库提供未来的更新,这一点很重要。为了使 COM 工作,您需要提供一个 uuid。例如。在partial class UserControl1
之前的文件'UserControl1.Designer.cs'中:
using System.Runtime.InteropServices;
using Microsoft.Win32;
[ProgId("Transporter.UserControl1")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("12fC4E0E-DC1E-A5dc-912B-A631740FG63A")] // generate your own one!
[ComVisible(true)]
然后将这两个成员添加到您的 UserControl1
类中:
///<summary>
///Register the class as a control and set its CodeBase entry
///</summary>
///<param name="key">The registry key of the control</param>
[ComRegisterFunction()]
public static void RegisterClass(string key)
// System.Windows.Forms.MessageBox.Show("Registered!");
///<summary>
///Called to unregister the control
///</summary>
///<param name="key">The registry key</param>
[ComUnregisterFunction()]
public static void UnregisterClass(string key)
// System.Windows.Forms.MessageBox.Show("Unregistered!");
最后,添加你要调用的函数:
[ComVisible(true)]
public int StartRequest(string baseAddress, string content, string token, string userName, string password)
int returnCode = 0;
// do something here
return returnCode;
请注意,.NET 类库和非托管 C++ COM DLL (.ocx) 之间存在更多差异,因为 win32 和 .NET 是完全不同的生态系统。例如,您可以使用regasm.exe
而不是regsrv32.exe
注册组件。
有关如何以编程方式调用 StartRequest()
的详细示例,请查看此答案的下半部分:https://***.com/a/47050380/1284927(这是 MFC 9.0 代码,但也应适用于 MFC 6.0。)
【讨论】:
谢谢@thomiel,我会试试的。什么情况下需要使用LoadLibrary? @Ives 如果您想从 win32 代码访问 win32 dll,请使用LoadLibrary()
。 (MFC 只是 win32 API 的一个包装器。)以上是关于从 Visual C# 2019 创建的 DLL 可以在 MFC 6.0 中使用吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual C++ 中使用使用 C# 创建的 dll?
从 Visual Studio 2017 中的现有 VB.NET 项目创建 dll
使用 C++ Dll 的 LNK2019 构造函数/析构函数
如何解决 Visual Studio 2019 中的这个 dll 缺失问题?