读硬盘的物理序列号,有些情况下读不出,比如SCSI硬盘,或是用户用了虚拟机,都读不出的,据说现在很流行的SATA硬盘也读不出。
我的方法是:如果能取到物理序列号,就用物理序列号,如果取不到就用卷序列号。
伪代码:
-------------------------------
取一下物理序列号
if 成功 then
用物理序列号
else
用卷序列号
end if
--------------------------------
要想判断取物理序列号是否成功,要经过三重判断。
第一道:如果取到的8个字节都是0,那么说明失败了。
第二道:取完第一次后再取一次,如果两次的结果不同,说明你取到的物理序列号是个随机值,也不能用,也算失败。
第三道:出现API异常,也说明失败了。需要用API做异常替换,拦截API的异常,以保证在vb中处理。
至于说怎么取到卷序列号,就比较简单了,可以用API函数GetVolumeInformation,可以参考msdn,无须赘述。
我有一个取硬盘物理序列号的完整代码,做了上述的所有处理,比较稳固,可以拿来用。Dll文件是从
appleVB 下载的:(感谢www.applevb.com)。
源码及DLL文件的下载地址是:http://lqweb.crPhysical_ID.zip
---------------------------------------------------------------------------------------------------------------------------
再来详细的解说一下上述代码中用到的截获DLL异常的方法:要想截获DLL异常,需要用到一个API函数SetUnhandledExceptionFilter。
SetUnhandledExceptionFilter的功能是替换系统默认的异常处理函数。 程序运行中所有得不到处理的异常都要经过全局异常处理函数来处理。用这个函数可以把系统默认的全局异常处理函数替换成一个普通的VB函数,替换之后,程序运行中发生的所有得不到处理的异常都要由这个VB中的函数来处理。更详细的信息请参考msdn.
参数 ByVal lpTopLevelExceptionFilter As Long 就是你要替换的函数的地址。如果把该参数设置为0,则表示还原系统默认的全局异常处理函数。
你可以试一下,在一个标准模块中定义一个替代全局异常处理函数的普通VB函数,定义如下:
''新的异常处理函数
Public Function NewExceptionHandler( _
ByRef lpExceptionPointers As EXCEPTION_POINTERS) As Long
msgbox "截获了系统异常 "
End Function
然后在form_load事件中,写如下代码:
SetUnhandledExceptionFilter addressof NewExceptionHandler
form_unload中写如下代码:
SetUnhandledExceptionFilter 0&
接下来运行程序,就可以截获异常了,包括外部DLL所引发的异常也能截获,大大增强了VB程序的除错机制。
我把全部代码发上来,可以参考一下。
module1.bas----------------------------------------------------------------
Option Explicit
''替换系统的默认错误处理程序的函数。
Public Declare Function SetUnhandledExceptionFilter _
Lib "kernel32 " (ByVal lpTopLevelExceptionFilter As Long) _
As Long
Private Type EXCEPTION_POINTERS
pExceptionRecord As Long
ContextRecord As Long
End Type
''新的异常处理函数
Public Function NewExceptionHandler( _
ByRef lpExceptionPointers As EXCEPTION_POINTERS) AsLong
MsgBox "截获了系统异常! "
End Function
--------------------------------------------------------------------------
form1.frm-----------------------------------------------------------------
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32 " Alias "RtlMoveMemory " (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Command1_Click()
CopyMemory ByVal 0&, 8&, 4
End Sub
Private Sub Form_Load()
SetUnhandledExceptionFilter AddressOf NewExceptionHandler
End Sub
Private Sub Form_Unload(Cancel As Integer)
SetUnhandledExceptionFilter 0&
End Sub