我的知识超出.Net非常有限 - 但我花了很多时间阅读许多相关文章。
HCRYPTPROV datatype documentaion表示它的类型为ULONG_PTR
。
以下参考资料建议使用与此相对应的IntPtr
。
但是,在下面的代码中我使用的是long
数据类型,它的工作正常。有什么情况会给出不正确的结果吗?它与long
合作的原因是什么?
框架:.Net 2.0;
架构:64位;
操作系统:Windows Server 2012 R2;
Visual Studio:2013
CODE
Module Module1
Private Declare Function CryptAcquireContext Lib "advapi32.dll" _
Alias "CryptAcquireContextA" ( _
ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, _
ByVal dwProvType As Integer, ByVal dwFlags As Integer) As Integer
Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, _
ByVal Algid As Integer, ByVal hKey As Integer, ByVal dwFlags As Integer, _
ByRef phHash As Integer) As Integer
Private Declare Function GetLastError Lib "kernel32" () As Integer
Sub Main()
Dim sClearText As String
sClearText = "test1"
Dim lHCryptprov As Long
Dim sProvider As String
Const MS_DEF_PROV As String = "Microsoft Base Cryptographic Provider v1.0"
Dim lHHash As Integer
Dim sInputBuffer As String
Const ALG_CLASS_HASH As Integer = 32768
Const ALG_TYPE_ANY As Integer = 0
Const ALG_SID_MD5 As Integer = 3
Const PROV_RSA_FULL As Integer = 1
Const CRYPT_MACHINE_KEYSET As Integer = &H20
Const CALG_MD5 As Integer = ((ALG_CLASS_HASH Or ALG_TYPE_ANY) Or ALG_SID_MD5)
sInputBuffer = sClearText
'Get handle to the default CSP
sProvider = MS_DEF_PROV & vbNullChar
Dim errorCode As Integer
Dim r As Long
r = CryptAcquireContext(lHCryptprov, "", sProvider, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)
errorCode = GetLastError()
Dim hashResult As Boolean
hashResult = CBool(CryptCreateHash(lHCryptprov, CALG_MD5, 0, 0, lHHash))
errorCode = GetLastError()
Console.WriteLine(hashResult)
Console.ReadLine()
End Sub
End Module
答案 0 :(得分:2)
架构:64位;
这最有可能让你摆脱困境。 ULONG_PTR是一个整数类型,其大小取决于进程的位数。在32位进程中它是32位,在64位进程中它是64位。最直接的.NET类型等价物是UIntPtr
。
这里的用法是作为句柄,实际值无关紧要。您不对该值执行任何算术,您可以从CryptAcquireContext()获取它并将其传递给CryptCreateHash()。因此,您在pinvoke声明中选择的类型是有符号还是无符号无关紧要。 IntPtr
是更常见的建议的原因,它是[CLSCompliant]类型。
VB.NET中的Long
是64位有符号整数类型。因此,当程序作为64位进程运行时,匹配ULONG_PTR。
如果没有,你可能会遇到麻烦。要么是因为您的程序在具有32位操作系统的计算机上运行,要么在VS2013上使用新项目的默认设置时运行。相关设置是Project>属性>编译标签>目标CPU。将它从AnyCPU更改为x86以解决问题。请注意,还有“首选32位”复选框,因为您以.NET 2.0
为目标而被禁用在进行此更改后启动程序时,现在应该在调用CryptCreateHash()时获得调试器中断。有一个名为PInvokeStackImbalance的专用托管调试助手应该注意到,当函数返回时,堆栈已经超出了4。并调用一个调试器中断来告诉你它。堆栈不平衡是一个非常讨厌的问题,可能导致任意程序失败,包括但不限于此站点命名的问题,尤其是在发布版本中。如果没有MDA的帮助,很难调试。
故意错误地使用IntPtr
,因此它与本机类型匹配。更正确的是当你声明它HandleRef
时。这是一个包装器,确保在本机代码忙于执行时不能销毁句柄,如果你有一个调用CryptReleaseContext()的Finalize()方法,则应该使用它。更正确的是使用安全的句柄包装类型,如.NET Framework does,它有一个关键的终结器,即使程序严重爆炸也会运行。只有在代码在非托管主机程序内部运行时才真正需要,SQL Server作为一个常见示例。