提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!

安装序列号又称为CD-KEY或者Product-Key,主要是用来验证用户是否是软件的合法拥有者,当第一次安装时可能会要求输入,输入正确后,软件才能正常安装并使用,并且以后不再需要输入这个序列号,由于序列号是唯一的,只在软件第一次安装或运行时需要,而且多数软件商喜欢把这个号写在产品说明书或者光盘上,不过随着时间的流逝我们有可能丢失这些印有序列号的说明书或者光盘,然后某一天当我们发现需要重新安装软件时,彻底杯具了。

不过下面我介绍的软件可能会补救一下,一般这些软件商喜欢在第一次输入序列号后将序列号存储入系统的注册表里,所以我们可以读取注册表来获取这类重要信息,比如说Windows XP/Vista/7操作系统的序列号就存储在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion 注册表路径下,键名称为DigitalProductId,不过貌似是二进制的,没关系,我在这里为大家准备了读取Windows XP系统信息的WScript/VBScript脚本,其中有一项就是解码并获取系统安装序列号:

Option Explicit

Const HKEY_LOCAL_MACHINE = &H80000002
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7

Class RegistryItem
  Public ValueName
  Public Value
  Public ValueType
End Class

Class WinInfo
  Private strComputer
  Private Registry
  Private OriginalSnap
  Private PendingChanges
  Private strKeyPath
  
  Private Sub Class_Initialize()
    strComputer = "."
    strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
  
    Set Registry = GetObject(_
      "winmgmts:{impersonationLevel=impersonate}!\\" &_
      strComputer & "\root\default:StdRegProv")
    
    Set OriginalSnap = WScript.CreateObject("Scripting.Dictionary")
    Set PendingChanges = WScript.CreateObject("Scripting.Dictionary")
  End Sub
 
  Private Sub Class_Terminate()
    PendingChanges.RemoveAll
    OriginalSnap.RemoveAll
    Set PendingChanges = Nothing
    Set OriginalSnap = Nothing
    Set Registry = Nothing
  End Sub
  
  ' 解码序列号,貌似Win2008 Server R2下解码不正确
  ' parseProductId函数来自elffin ( http://hi.baidu.com/elffin )
  Private Function parseProductId(rpk)
    Const rpkOffset=52
    Dim dwAccumulator, szPossibleChars
    Dim i,j

    i=28 : szPossibleChars="BCDFGHJKMPQRTVWXY2346789"
    Do 'Rep1
      dwAccumulator=0 : j=14
      Do
        dwAccumulator=dwAccumulator*256
        dwAccumulator=rpk(j+rpkOffset)+dwAccumulator
        rpk(j+rpkOffset)=(dwAccumulator\24) and 255
        dwAccumulator=dwAccumulator Mod 24
        j=j-1
      Loop While j>=0
      i=i-1
      parseProductId=mid(szPossibleChars,dwAccumulator+1,1) & parseProductId
      If (((29-i) Mod 6)=0) And (i<>-1) Then
        i=i-1
        parseProductId="-"&parseProductId
      End If
    Loop While i>=0 'Goto Rep1
  End Function
  
  Private Function parseLicenseInfo(arrBinaryDigits)
    Dim i
    For i = lBound(arrBinaryDigits) to uBound(arrBinaryDigits)
      parseLicenseInfo = parseLicenseInfo & " " & Hex(arrBinaryDigits(i))
    Next
    parseLicenseInfo = Trim(parseLicenseInfo)
  End Function
  
  Public Function getKeyCollection()
    getKeyCollection = OriginalSnap.Keys
  End Function
  
  Public Function getCount()
    getCount = OriginalSnap.Count
  End Function
  
  Public Function getItem(ByVal sName)
    If OriginalSnap.Exists(sName) Then
      Set getItem = OriginalSnap.Item(sName)
    End If
  End Function
  
  Private Function parseInstallDate(lngValue)
  parseInstallDate = DateAdd("s", lngValue, "01/01/1970 00:00:00")
  End Function
  
  Public Function getItemValue(ByVal sName)
    If OriginalSnap.Exists(sName) Then
      getItemValue = OriginalSnap.Item(sName).Value
      Select Case sName
      Case "DigitalProductId","DigitalProductId4"
        getItemValue = parseProductId(getItemValue)
      Case "LicenseInfo"
        getItemValue = parseLicenseInfo(getItemValue)
      Case "InstallDate"
        getItemValue = parseInstallDate(getItemValue)
      End Select
    End If
  End Function
  
  Public Function getItemType(ByVal sName)
    If OriginalSnap.Exists(sName) Then
      getItemType = OriginalSnap.Item(sName).ValueType
    End If
  End Function
  
  ' 加载设置
  Public Function load()
    Dim item, strValue
    Dim i, arrValueNames, arrValueTypes
    Registry.EnumValues HKEY_LOCAL_MACHINE, strKeyPath,_
      arrValueNames, arrValueTypes
    
    For i=0 To UBound(arrValueNames)
      Set item = New RegistryItem
        item.ValueName = arrValueNames(i)
        item.ValueType = arrValueTypes(i)
      
        Select Case arrValueTypes(i)
          Case REG_SZ
            Registry.GetStringValue HKEY_LOCAL_MACHINE,_
              strKeyPath,_
              arrValueNames(i),_
              strValue
          Case REG_EXPAND_SZ
            Registry.GetExpandedStringValue HKEY_LOCAL_MACHINE,_
              strKeyPath,_
              arrValueNames(i),_
              strValue
          Case REG_BINARY
            Registry.GetBinaryValue HKEY_LOCAL_MACHINE,_
              strKeyPath,_
              arrValueNames(i),_
              strValue
          Case REG_DWORD
            Registry.GetDWORDValue HKEY_LOCAL_MACHINE,_
              strKeyPath,_
              arrValueNames(i),_
              strValue
          Case REG_MULTI_SZ
            Registry.GetMultiStringValue HKEY_LOCAL_MACHINE,_
              strKeyPath,_
              arrValueNames(i),_
              strValue
        End Select
        item.Value = strValue
        OriginalSnap.Add arrValueNames(i), item
      Set item = Nothing
    Next
  End Function

  ' 保存设置开始,尚未实现!
  Public Function setItem(ByVal sName, ByVal sValue)
    If OriginalSnap.Exists(sName) Then
  
    End If
  End Function
  
  Public Function setItemType(ByVal sName, ByVal sValue)
  
  End Function
  
  Public Function save()
  
  End Function
  ' 保存设置结束
End Class

Function VBMain()
  ON ERROR RESUME NEXT
  Dim Info, Keys
  Set Info = New WinInfo
  Info.load
  
  Keys = Info.getKeyCollection
  
  Dim i, s
  For i = 0 To Info.getCount - 1
      s = s & Keys(i) & " = " & Info.getItemValue(Keys(i)) & vbCrLf
  Next
  MsgBox s
  Set Info = Nothing

  If Err Then Err.Clear
End Function

Call WScript.Quit(VBMain)

这个脚本可以正确解码并获取Windows XP和Windows 7的序列号(Vista未做尝试),Windows 2008 Server R2有DigitalProductId和DigitalProductId4(Windows 7也有),不知道DigitalProductId4是做什么用的,不过这两个字段值用上述脚本解码都是有问题的。

什么?只能获取Windows XP/7这样的操作系统的序列号?太不给力了吧!好吧,下面我再介绍两款强大而且免费的查看已安装软件序列号的工具,一款是 Magical Jelly Bean的KeyFinder(主页) ,软件截图如下:

KeyFinder序列号查看器.png

这是一款可以获取上百种著名软件信息的小工具,虽说它有功能更为强大的收费版,但是免费版就已经足够我们使用了,更重要的是其配置文件keyfinder.cfg可以让我们自定义要获取软件信息的注册表路径及类型,我们可以使用其 官方版本的keyfinder.cfg 来配置我们的keyfinder程序。

另外一款是著名小工具开发商 NirSoft开发的ProduKey(主页) ,NirSoft开发的工具以实用出名,这次也不例外,这个工具简单易用,直接运行就能列出常用软件的序列号,软件截图如下:

NirSoft Produkey 序列号查看器.png

由于准备重装系统,我尝试了这两款工具,总体上来说KeyFinder的识别软件较多,可配置性强,唯一遗憾的是没有Office的选项,我电脑上装有Office 2010,哪怕是修改配置文件,也不能读出序列号。然后据官方介绍我又下载了Recover Keys这款软件,虽说是收费的,但是其试用版依旧不能识别我电脑上安装的Office 2010;相比之下ProduKey则简单得多,虽然识别软件没有前者那么多,但是却能准确识别出电脑上的Office版本和序列号,这点相当不错,据官方介绍“ProduKey is a small utility that displays the ProductID and the CD-Key of Microsoft Office (Microsoft Office 2003, Microsoft Office 2007), Windows (Including Windows 7 and Windows Vista), Exchange Server, and SQL Server installed on your computer.”,纳尼?没有Office 2010,只有2007,但是2010确实被识别出来了,难道是Office 2007和2010的序列号是一种编码模式?

好了,就介绍这么多,更多的功能还是大家去发掘吧:-)