在 VBA 中使用 UnmanagedExports 包 [DllExport] 调用 C# DLL 触发“找不到 DLL 入口点”错误
Posted
技术标签:
【中文标题】在 VBA 中使用 UnmanagedExports 包 [DllExport] 调用 C# DLL 触发“找不到 DLL 入口点”错误【英文标题】:Using UnmanagedExports Package [DllExport] to call C# DLL in VBA Triggers "Can't Find DLL Entry Point" Error 【发布时间】:2022-01-19 05:35:28 【问题描述】:我正在使用Robert Giesecke's Unmanaged Exports 包来访问 Excel VBA 中的 c# dll。我遵循了几个示例并继续得到运行时错误 453:“在 myDllName.dll 中找不到入口点 MyDLLFunction”
我在使用 64 位 Excel 的 64 位机器上,正在为 x64 打包 dll。
我正在使用 Visual Studio 2022 并尝试在 .NET 6.0 和 .Net Framework 4.7.2 中准备 dll。
这是我导出的类:
namespace MyNamespace
public static class UnmanagedExports
//entry point for dll
static UnmanagedExports()
//nothing
[DllExport("HelloWorld", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static string HelloWorld()
return "Hello World";
[DllExport("MyDLLFunction", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.IDispatch)]
static object MyDLLFunction()
return new InnerNamespace.MyCsharpClass();
然后这是我的另一个 C#:
namespace MyNamespace.InnerNamespace
[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class MyCsharpClass
[return: MarshalAs(UnmanagedType.BStr)]
public async Task<string> InnerFunction(string LookupType, string LookupNumber)
object Response = await GetResponseAsync(LookupType, LookupNumber);
string ResultAsString = Response.ToString();
return ResultAsString;
在 Excel VBA 中:
Private Declare PtrSafe Function AddDllDirectory Lib "kernel32" (ByVal lpLibFileName As String) As Integer
Public Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
Public Declare PtrSafe Function MyDLLFunction Lib "C:\my\long\path\to\my\project\bin\x64\Debug\net472\myDllName.dll" () As Object
Sub Test()
Dim mObj As Object
Set mscObj = MyDLLFunction() //run time error here <- can't find entry point
End Sub
我关注了this example,但它不起作用。
我已经用谷歌搜索并测试了各种配置,但无法通过错误“找不到入口点”。
【问题讨论】:
没有名为“MyFunction”的函数,当您为此类事故寻求帮助时,拼写错误非常重要。照原样,没有任何迹象表明包完成了它的工作,通过在 DLL 上运行 Dumpbin.exe /exports 进行仔细检查。 您声明static object MyDLLFunction()
,所以默认情况下它是私有的。尝试将其更改为公开。您也可以尝试将返回类型声明为 MyCsharpClass
而不是 object
。
但是这里还有另一个问题:InnerFunction
返回一个Task<string>
而不是一个字符串。但是没有明显的方法可以通过 P/Invoke 编组 Task<string>
——我当然不知道如何。如果可能的话,我不知道如何在 VBA 中等待它。有什么方法可以在c#中等待结果,并返回字符串,即public string InnerFunction(string LookupType, string LookupNumber)
?
所以可能相关:How to call asynchronous method from synchronous method in C#?,还有Async P/Invoke calls、Excel VBA make a script asynchronous(答案:否)和Wait for C# asynchronous function to finish executing in VBA?(从未回答)。
然后我会缩小你的问题范围,只问这个问题,然后一旦你有这个工作,就更复杂的情况询问后续行动。但非托管导出甚至可能不会为 .NET Core 实现,它自 2015 年以来就没有更新。并且该包可能不再维护,请参阅github.com/3F/DllExport/issues/87#issuecomment-438576100。
【参考方案1】:
我相信它是固定的。我终于能够在 dumpbin /exports 输出中看到导出的函数。我认为需要做几件事来纠正这个问题。希望这对将来的某人有所帮助。
打包未更新 - 尝试旧版本的 VS
根据包的年龄,我怀疑它在 VS2022 中不支持,所以,我:
在 Visual Studio 2015 中创建项目(与我使用的 VS2022 相比) 从头开始重建项目并添加对新项目的引用,而不是尝试在 VS2015 中打开旧项目DllExportAppDomainIsolatedTask 错误
然后,项目无法构建,它一直抛出错误:
The "DllExportAppDomainIsolatedTask" task failed unexpectedly.
基于this answer我:
为 VS2015 安装了 Microsoft Build Tools 安装 .NET 3.5 并手动添加 Microsoft.Build.Tasks.v3.5 作为对我的项目的引用,方法是在 .NET3.5 安装后浏览到其位置但我一直收到同样的错误。然后,我通过更改设置来增加调试输出:Project>Properties>Build>Errors and Warnings>Warning Level to 4。
通过调试日志,我从 UnmanagedExports 包中找到了几行,其中引用了项目平台、框架路径、库工具路径、工具 dll 路径等。在该部分中,我发现:
System.ArgumentException: Requested value 'Version47' was not found.
我的目标是 .NET Framework 4.7.2,所以我将项目降级为目标 .NET Framework 4.5,删除 bin/obj 文件夹内容并重建项目。然后,运行 dumpbin /exports 显示了我的 HelloWorld 函数!
该软件包似乎与 .NET Framework 4.7.2 不兼容。
【讨论】:
以上是关于在 VBA 中使用 UnmanagedExports 包 [DllExport] 调用 C# DLL 触发“找不到 DLL 入口点”错误的主要内容,如果未能解决你的问题,请参考以下文章