分類: Windows

如何從電腦中找出 Windows 或 Office 的產品金鑰

這裡介紹如何從電腦中找出 Windows 或 Office 的產品金鑰,讓重灌電腦時不必煩惱找不到序號。

Windows 用久了難免需要重灌,而安裝 Windows 與 Office 時都會需要輸入產品序號,但是如果序號不見了,就很令人頭痛了。

雖然我們可以用登錄編輯程式(regedit.exe)來從登錄檔找出產品序號(路徑為 HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsNTCurrent VersionDigitalProductId):

不過因為在登錄檔中所儲存的序號都是二進位的形式,不容易看出真正的序號,以下介紹幾種可以解讀序號的方式。

使用 VBScript 讀取 Windows 序號

我們可以用 VBScript 撰寫一個讀取序號的指令稿,這樣的方式完全不需要下載與安裝任何軟體。將下面這段程式碼複製起來,儲存成一個 .vbs 檔(如 getkey.vbs):

Set WshShell = CreateObject("WScript.Shell")
MsgBox ConvertToKey(WshShell.RegRead("HKLMSOFTWAREMicrosoftWindows NTCurrentVersionDigitalProductId"))

Function ConvertToKey(Key)
Const KeyOffset = 52
i = 28
Chars = "BCDFGHJKMPQRTVWXY2346789"
Do
Cur = 0
x = 14
Do
Cur = Cur * 256
Cur = Key(x + KeyOffset) + Cur
Key(x + KeyOffset) = (Cur  24) And 255
Cur = Cur Mod 24
x = x -1
Loop While x >= 0
i = i -1
KeyOutput = Mid(Chars, Cur + 1, 1) & KeyOutput
If (((29 - i) Mod 6) = 0) And (i <> -1) Then
i = i -1
KeyOutput = "-" & KeyOutput
End If
Loop While i >= 0
ConvertToKey = KeyOutput
End Function

建議將這個 getkey.vbs 檔案儲存在桌面上,然後用滑鼠點兩下執行,就會出現自己 Windows 的序號了。

在這個顯示序號的視窗上按下 Ctrl + c 就可以直接複製這組序號。

使用 VBScript 讀取 Office 序號

這裡有已經寫好的指令稿可以參考,這是適用於 Windows 7、Windows 10 與 Office 2010 – 2013 的指令稿:

Const HKLM = &H80000002

wscript.echo "View Product Keys | Microsoft Products" & vbCrLf

'Install Date 
Computer = "."
Set objWMIService = GetObject("winmgmts:" & Computer & "rootcimv2")
Set Obj = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")

dim InsDate

For Each item in Obj
  InsDate = item.InstallDate
  ' Gather Operating System Information
  Caption = Item.Caption
  OSArchitecture = Item.OSArchitecture
  CSDVersion = Item.CSDVersion
  Version = Item.Version
  Next

dim NewDate

NewDate = mid(InsDate,9,2) & ":" & mid(InsDate,11,2) & ":" & mid(InsDate,13,2)
NewDate = NewDate & " " & mid(InsDate,7,2) & "/" & mid(InsDate,5,2) & "/" & mid(InsDate,1,4)

QueryWindowsProductKeys()

wscript.echo 'vbCrLf & "Office Keys" & vbCrLf

QueryOfficeProductKeys()

Function DecodeProductKey(arrKey, intKeyOffset)
  If Not IsArray(arrKey) Then Exit Function
    intIsWin8 = BitShiftRight(arrKey(intKeyOffset + 14),3) And 1
    arrKey(intKeyOffset + 14) = arrKey(intKeyOffset + 14) And 247 Or BitShiftLeft(intIsWin8 And 2,2)
    i = 24
    strChars = "BCDFGHJKMPQRTVWXY2346789"
    strKeyOutput = ""
    While i > -1
        intCur = 0
        intX = 14
        While intX > -1
            intCur = BitShiftLeft(intCur,8)
            intCur = arrKey(intX + intKeyOffset) + intCur
            arrKey(intX + intKeyOffset) = Int(intCur / 24)
            intCur = intCur Mod 24
            intX = intX - 1
        Wend
        i = i - 1
        strKeyOutput = Mid(strChars,intCur + 1,1) & strKeyOutput
        intLast = intCur
    Wend
    If intIsWin8 = 1 Then
        strKeyOutput = Mid(strKeyOutput,2,intLast) & "N" & Right(strKeyOutput,Len(strKeyOutput) - (intLast + 1))
    End If
    strKeyGUIDOutput = Mid(strKeyOutput,1,5) & "-" & Mid(strKeyOutput,6,5) & "-" & Mid(strKeyOutput,11,5) & "-" & Mid(strKeyOutput,16,5) & "-" & Mid(strKeyOutput,21,5)
    DecodeProductKey = strKeyGUIDOutput
End Function

Function RegReadBinary(strRegPath,strRegValue)
    Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!.rootdefault:StdRegProv")
    objReg.GetBinaryValue HKLM,strRegPath,strRegValue,arrRegBinaryData
    RegReadBinary = arrRegBinaryData
    Set objReg = Nothing
End Function

Function BitShiftLeft(intValue,intShift)
    BitShiftLeft = intValue * 2 ^ intShift
End Function

Function BitShiftRight(intValue,intShift)
    BitShiftRight = Int(intValue / (2 ^ intShift))
End Function

Function QueryOfficeProductKeys()

        strBaseKey = "SOFTWARE"

        strOfficeKey = strBaseKey & "MicrosoftOffice"
        Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!.rootdefault:StdRegProv")
        objReg.EnumKey HKLM, strOfficeKey, arrOfficeVersionSubKeys
        intProductCount = 1
        If IsArray(arrOfficeVersionSubKeys) Then

            For Each strOfficeVersionKey In arrOfficeVersionSubKeys

                Select Case strOfficeVersionKey
                    Case "11.0"
                        CheckOfficeKey strOfficeKey & "11.0Registration",52,intProductCount
                    Case "12.0"
                        CheckOfficeKey strOfficeKey & "12.0Registration",52,intProductCount
                    Case "14.0"
                        CheckOfficeKey strOfficeKey & "14.0Registration",808,intProductCount
                    Case "15.0"
                        CheckOfficeKey strOfficeKey & "15.0Registration",808,intProductCount
                End Select
            Next
        End If

        strBaseKey = "SOFTWAREWow6432Node"

        strOfficeKey = strBaseKey & "MicrosoftOffice"
        Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!.rootdefault:StdRegProv")
        objReg.EnumKey HKLM, strOfficeKey, arrOfficeVersionSubKeys
        intProductCount = 1

        If IsArray(arrOfficeVersionSubKeys) Then

            For Each strOfficeVersionKey In arrOfficeVersionSubKeys

                Select Case strOfficeVersionKey
                    Case "11.0"
                        CheckOfficeKey strOfficeKey & "11.0Registration",52,intProductCount
                    Case "12.0"
                        CheckOfficeKey strOfficeKey & "12.0Registration",52,intProductCount
                    Case "14.0"
                        CheckOfficeKey strOfficeKey & "14.0Registration",808,intProductCount
                    Case "15.0"
                        CheckOfficeKey strOfficeKey & "15.0Registration",808,intProductCount
                End Select
            Next
        End If
End Function

'Office Product Key
Sub CheckOfficeKey(strRegPath,intKeyOffset,intProductCount)

    Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!.rootdefault:StdRegProv")
    objReg.EnumKey HKLM, strRegPath, arrOfficeRegistrations
    If IsArray(arrOfficeRegistrations) Then
        For Each strOfficeRegistration In arrOfficeRegistrations

            objReg.GetStringValue HKLM,strRegPath & "" & strOfficeRegistration,"ConvertToEdition",strOfficeEdition
            objReg.GetBinaryValue HKLM,strRegPath & "" & strOfficeRegistration,"DigitalProductID",arrProductID
            If strOfficeEdition <> "" And IsArray(arrProductID) Then
                WriteData "Product", strOfficeEdition
                WriteData "Key", DecodeProductKey(arrProductID,intKeyOffset) & vbCrLf
                intProductCount = intProductCount + 1
            End If
        Next
    End If
End Sub


'Windows Product Key
Sub QueryWindowsProductKeys()
    strWinKey = CheckWindowsKey("SOFTWAREMicrosoftWindows NTCurrentVersion","DigitalProductId",52)
    If strWinKey <> "" Then
        wscript.echo "Product: " & Caption & Version & " (" & OSArchitecture & ")"
        wscript.echo "Installation Date: " & NewDate
        WriteData "Key", strWinKey
        Exit Sub
    End If
    strWinKey = CheckWindowsKey("SOFTWAREMicrosoftWindows NTCurrentVersion","DigitalProductId4",808)
    If strWinKey <> "" Then
        wscript.echo "Product: " & Caption & Version & " (" & OSArchitecture & ")"
        wscript.echo "Installation Date: " & NewDate
        WriteData "Key", strWinKey
        Exit Sub
    End If
    strWinKey = CheckWindowsKey("SOFTWAREMicrosoftWindows NTCurrentVersionDefaultProductKey","DigitalProductId",52)
    If strWinKey <> "" Then
        wscript.echo "Product: " & Caption & Version & " (" & OSArchitecture & ")"
        wscript.echo "Installation Date: " & NewDate
        WriteData "Key", strWinKey
        Exit Sub
    End If
    strWinKey = CheckWindowsKey("SOFTWAREMicrosoftWindows NTCurrentVersionDefaultProductKey","DigitalProductId4",808)
    If strWinKey <> "" Then
        wscript.echo "Product: " & Caption & Version & " (" & OSArchitecture & ")"
        wscript.echo "Installation Date: " & NewDate
        WriteData "Key", strWinKey
        Exit Sub
    End If
End Sub

Function CheckWindowsKey(strRegPath,strRegValue,intKeyOffset)
    strWinKey = DecodeProductKey(RegReadBinary(strRegPath,strRegValue),intKeyOffset)
    If strWinKey <> "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB" And strWinKey <> "" Then
        CheckWindowsKey = strWinKey
    Else
        CheckWindowsKey = ""
    End If
End Function

Function RegReadBinary(strRegPath,strRegValue)
    Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!.rootdefault:StdRegProv")
    objReg.GetBinaryValue HKLM,strRegPath,strRegValue,arrRegBinaryData
    RegReadBinary = arrRegBinaryData
    Set objReg = Nothing
End Function

Function OsArch()
    Set objShell = WScript.CreateObject("WScript.Shell")
    If objShell.ExpandEnvironmentStrings("%ProgramFiles(x86)%") = "%ProgramFiles(x86)%" Then
        OsArch = "x86"
    Else
        OsArch = "x64"
    End If
    Set objShell = Nothing
End Function

Sub WriteData(strProperty,strValue)

    WScript.Echo strProperty & ": " & Trim(strValue)

    'Set objShell = CreateObject("WScript.Shell")
    'strKey = "HKLMSOFTWARECentraStageCustom" & strProperty
    'objShell.RegWrite strKey,Trim(strValue),"REG_SZ"
    'Set objShell = Nothing

End Sub

ProduKey

NirSoft 所提供的 ProduKey 是一個很好用的免費小工具,它可以將系統中的 Windows 與 Office 序號一次都抓取出來,非常方便,不過缺點是有些防毒軟體會將這個工具判斷為惡意程式,因為它會竊取您的序號。

名稱:ProduKey
網址:www.nirsoft.net

從 NirSoft 網站上將 ProduKey 的壓縮檔下載回來,解壓縮之後直接就可以使用,不需要安裝。

ProduKey 除了可以取得目前系統的序號之外,也可以從其他的資料來源中尋找序號。

這個工具也非常實用,假設我們的 Windows 系統出了問題,無法正常開機的時候,我們就可以直接把硬碟拔下來,插在另外一台正常的電腦上,用這個工具將出問題系統的序號取出來。

參考資料:HTG

G. T. Wang

個人使用 Linux 經驗長達十餘年,樂於分享各種自由軟體技術與實作文章。

Share
Published by
G. T. Wang

Recent Posts

光陽 KYMCO GP 125 機車接電發動、更換電瓶記錄

本篇記錄我的光陽 KYMCO ...

2 年 ago

[開箱] YubiKey 5C NFC 實體金鑰

本篇是 YubiKey 5C ...

2 年 ago

[DIY] 自製竹火把

本篇記錄我拿竹子加上過期的苦茶...

3 年 ago