我正在从VBA加载一些旧的VB函数,并且大多数都已经更新到VB.NET,但是“wininet.dll”中的函数有函数声明似乎没有正确匹配。
我得到的错误是:
异常抛出:托管调试助手,'PInvokeStackImbalance':...
它的长短是声明的参数的长度需要是显式的,并且它与dll中的实际函数不匹配。
我看了这个,我可以通过删除支票来解决,但它会产生“堆栈不平衡”,并且随着时间的推移最终会耗尽所有堆栈。此外,这些被称为“非托管”dll,并且在http://pinvoke.net处的PInvoke函数wiki上已经提出了一些声明。这个wiki确实有一些我正在使用的函数调用,但不是全部。其中一些我不得不猜测一些事情,但这没有成功。
我从旧代码中复制的大部分更改都从long
更改为int32
或integer
,并对IntPtr
进行了一些更改,这些更改从未在旧代码中使用。我假设这会使所有整数大小正确(即16/32/64位),这可能是大多数问题所在。但有一种情况是从long
变为string()
,这似乎有点奇怪,并且没有编译好。
那么,我如何实际查找dll中的函数长度并匹配API?
我查了几件事,但当我尝试在Visual Studio中添加对c:\ windows \ system32 \ wininet.dll的引用到我的VB.NET项目时,它说我无法添加它。这似乎阻止我在Visual Studio中使用Object或Assembly浏览器。它似乎不是COM对象。这里有什么帮助吗?
作为参考,这是失败的旧代码:
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" ( _
ByVal Agent As String, ByVal AccessType As Long, ByVal ProxyName As String, _
ByVal ProxyBypass As String, ByVal Flags As Long) As Long
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" ( _
ByVal hInternetSession As Long, ByVal ServerName As String, ByVal ServerPort As Integer, ByVal UserName As String, _
ByVal Password As String, ByVal Service As Long, ByVal Flags As Long, ByVal Context As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet.dll" ( _
ByVal hInet As Long) As Boolean
Private Declare Function InternetReadFile Lib "wininet.dll" ( _
ByVal hConnect As Long, ByVal Buffer As String, ByVal NumberOfBytesToRead As Long, _
NumberOfBytesRead As Long) As Boolean
Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" ( _
ByVal hHttpSession As Long, ByVal Verb As String, ByVal ObjectName As String, ByVal Version As String, _
ByVal Referer As String, ByVal AcceptTypes As Long, ByVal Flags As Long, Context As Long) As Long
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" ( _
ByVal hHttpRequest As Long, ByVal Headers As String, ByVal HeadersLength As Long, _
ByVal sOptional As String, ByVal OptionalLength As Long) As Boolean
答案 0 :(得分:5)
已经noted by Hans Passant,您应该使用托管替代方案。
但是要回答您的实际问题:您基本上只需要检查MSDN文档文章Windows Data Types,并根据类型的声明确定相应的.NET类型。
例如,DWORD
:
<强> DWORD 强>
一个32位无符号整数。范围是0到4294967295十进制。此类型在IntSafe.h中声明如下:
typedef unsigned long DWORD;
在这种情况下,我们可以通过范围(0 - 4294967295)或定义(unsigned long
)来确定这应该是无符号的32位整数(UInt32
或{ {1}})。在C / C ++中,UInteger
与long
是相同的,这就是为什么它映射到整数而不是int
。
以下是最常见类型的摘要:
(非常感谢David Heffernan帮助我纠正一些字符串声明!)
Long/ULong