如何确定非托管dll的正确参数结构?

时间:2017-10-03 07:13:30

标签: vb.net visual-studio dll vb6-migration wininet

我正在从VBA加载一些旧的VB函数,并且大多数都已经更新到VB.NET,但是“wininet.dll”中的函数有函数声明似乎没有正确匹配。

我得到的错误是:

  

异常抛出:托管调试助手,'PInvokeStackImbalance':...

它的长短是声明的参数的长度需要是显式的,并且它与dll中的实际函数不匹配。

我看了这个,我可以通过删除支票来解决,但它会产生“堆栈不平衡”,并且随着时间的推移最终会耗尽所有堆栈。此外,这些被称为“非托管”dll,并且在http://pinvoke.net处的PInvoke函数wiki上已经提出了一些声明。这个wiki确实有一些我正在使用的函数调用,但不是全部。其中一些我不得不猜测一些事情,但这没有成功。

我从旧代码中复制的大部分更改都从long更改为int32integer,并对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

1 个答案:

答案 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 ++中,UIntegerlong是相同的,这就是为什么它映射到整数而不是int

以下是最常见类型的摘要:

(非常感谢David Heffernan帮助我纠正一些字符串声明!)

Long/ULong