Some customer asked me for this info, because managing Product Keys over the time can become a very time-wasting activity.
First of all you have to enable the Remote Registry Service, as we are in Windows domain, you can easily do this using a GPO
########################################################################################
# Script: GetMsProductKeys.ps1
# Objective: Get Windows and Office Product Keys from all domain computers
# created from: Ruggiero Lauria
# on : 25/03/2014
#
# http://ruggierolauria.blogspot.com
#
# Thanks to:
# http://poshcode.org/4488
# http://gallery.technet.microsoft.com/scriptcenter/Backup-Windows-product-key-b41468c2
########################################################################################
# Start Functions definition
# Get Windows Product Key
function Get-WindowsProductKey
{
Param (
[string[]]$Computername = $Env:Computername,
$version
)
$hklm = 2147483650
# Invoke the WMI RemoteRegistry access provider
$wmi = [WMIClass] ("\\" + $Computername + "\root\default:StdRegProv")
# Load DigitalProductId value
$values = [byte[]]($wmi.getbinaryvalue($hklm,"SOFTWARE\Microsoft\Windows NT\CurrentVersion","DigitalProductId").uvalue)
# Select the correct decode function based on Windows Version
if ($version -lt "6.2")
{
$keyproductid = Get-Windows7ProductKey($values)
}
else
{
$keyproductid = Get-Windows8ProductKey($values)
}
$keyproductid
}
#Decode Pre-Windows 8 Product Key
Function Get-Windows7ProductKey($Key)
{
$lookup = [char[]]("B","C","D","F","G","H","J","K","M","P","Q","R","T","V","W","X","Y","2","3","4","6","7","8","9")
$keyStartIndex = 0x34;
$keyEndIndex = [int]($keyStartIndex + 15);
$decodeLength = [int]29
$decodeStringLength = [int]15
$decodedChars = new-object char[] $decodeLength
$hexPid = new-object System.Collections.ArrayList
for ($i = $keyStartIndex; $i -le $keyEndIndex; $i++){ [void]$hexPid.Add($values[$i]) }
for ( $i = $decodeLength - 1; $i -ge 0; $i--)
{
if (($i + 1) % 6 -eq 0){$decodedChars[$i] = '-'}
else
{
$digitMapIndex = [int]0
for ($j = $decodeStringLength - 1; $j -ge 0; $j--)
{
$byteValue = [int](($digitMapIndex * [int]256) -bor [byte]$hexPid[$j]);
$hexPid[$j] = [byte] ([math]::Floor($byteValue / 24));
$digitMapIndex = $byteValue % 24;
$decodedChars[$i] = $lookup[$digitMapIndex];
}
}
}
$keyproduct = ''
$decodedChars | % { $keyproduct+=$_}
$keyproduct
}
# Decode Windows 8 Product Key
Function Get-Windows8ProductKey($Key)
{
$Keyoffset = 52
$isWin8 = [int]($Key[66]/6) -band 1
$HF7 = 0xF7
$Key[66] = ($Key[66] -band $HF7) -bOr (($isWin8 -band 2) * 4)
$i = 24
[String]$Chars = "BCDFGHJKMPQRTVWXY2346789"
do
{
$Cur = 0
$X = 14
Do
{
$Cur = $Cur * 256
$Cur = $Key[$X + $Keyoffset] + $Cur
$Key[$X + $Keyoffset] = [math]::Floor([double]($Cur/24))
$Cur = $Cur % 24
$X = $X - 1
}while($X -ge 0)
$i = $i- 1
$KeyOutput = $Chars.SubString($Cur,1) + $KeyOutput
$last = $Cur
}while($i -ge 0)
$Keypart1 = $KeyOutput.SubString(1,$last)
$Keypart2 = $KeyOutput.Substring(1,$KeyOutput.length-1)
if($last -eq 0 )
{
$KeyOutput = "N" + $Keypart2
}
else
{
$KeyOutput = $Keypart2.Insert($Keypart2.IndexOf($Keypart1)+$Keypart1.length,"N")
}
$a = $KeyOutput.Substring(0,5)
$b = $KeyOutput.substring(5,5)
$c = $KeyOutput.substring(10,5)
$d = $KeyOutput.substring(15,5)
$e = $KeyOutput.substring(20,5)
$keyproduct = $a + "-" + $b + "-"+ $c + "-"+ $d + "-"+ $e
$keyproduct
}
# Get Microsoft Office Product Key
function Get-MSOfficeProductKey {
Param(
[string[]]$Computername = $Env:Computername
)
$product = @()
$hklm = 2147483650
# If DigitalProductId not found in hklm\SOFTWARE\Microsoft\Office\..
# may be we have Office 32 Bit on 64 bit OS so the registry path becomes: SOFTWARE\Wow6432node\Microsoft\Office\..
$path = @("SOFTWARE\Wow6432node\Microsoft\Office","SOFTWARE\Microsoft\Office")
for ($p = 1; $p -ge 0; $p--) {
# Invoke the WMI RemoteRegistry access provider
$wmi = [WMIClass] ("\\" + $Computername + "\root\default:StdRegProv")
#Navigate 3 levels down the registry tree starting from actual $ path to find DigitalProductID
# i.e. HKLM\SOFTWARE\Microsoft\Office\11.0\Registration\{90120410-6000-11D3-8CFE-0150048383C9}
$subkeys1 = $wmi.EnumKey($hklm,$path[$p])
foreach ($subkey1 in $subkeys1.snames) {
$subkeys2 = $wmi.EnumKey($hklm,$path[$p]+"\$subkey1")
foreach ($subkey2 in $subkeys2.snames) {
$subkeys3 = $wmi.EnumKey($hklm,$path[$p]+"\$subkey1\$subkey2")
foreach ($subkey3 in $subkeys3.snames) {
$subkeys4 = $wmi.EnumValues($hklm,$path[$p]+"\$subkey1\$subkey2\$subkey3")
foreach ($subkey4 in $subkeys4.snames) {
#Looking for DigitalProductID key
if ($subkey4 -eq "DigitalProductId") {
# Load DigitalProductId value
$values = [byte[]]($wmi.getbinaryvalue($hklm,$path[$p]+"\$subkey1\$subkey2\$subkey3","DigitalProductId").uvalue)
$p = -1 # Key found: exit from path loop
#Decode DigitalProductId
$keyproductid = Get-Windows7ProductKey($values)
$keyproductid
}
}
}
}
}
}
}
# End Functions definition
# Start of Script body
# Define variables
$FilePath = "C:\scripts\ProductKey" # Change with your own path (must be created!) to store CSV output
$NewCSVObject = @()
# Write Columns headers: first output line
$NewCSVObject | Select "ClientName","OSArchitecture", "Username" , "Manufacturer", "Model", "Dev SerialNumber" ,"Office Version","Office SN", "Caption", "Version", "RegisteredUser", "OS SerialNumber", "WindowsPK" | Format-Table -AutoSize
# Get the list of active computer in AD.
Import-Module ActiveDirectory
$arrComputers = Get-ADComputer -Filter {enabled -eq $true} -properties *|select name | sort name
#$arrComputers = Get-ADComputer -Filter {enabled -eq $true} -properties *|Where {$_.name -like "nb-ac*"} |select name | sort name
# Computers Loop
foreach ($strComputer in $arrComputers)
{
Write-Host $strComputer.name
#Try to connect to the computer
If (Test-Connection -ComputerName $strComputer.name -Count 1 -Quiet) {
try {
#Inizialize a new row
$objInfo = New-Object PSObject | Select "ClientName", "OSArchitecture", "Username" ,"Manufacturer", "Model", "DevSerialNumber" ,"OfficeVersion", "OfficeSN", "Caption", "Version","RegisteredUser", "OSSerialNumber", "WindowsPK"
# Get currently logged in username, client name, manufacturer and model from Win32_ComputerSystem class.
$colItems = Get-WmiObject Win32_ComputerSystem -Namespace "root\CIMV2" -ErrorAction stop -ComputerName $strComputer.name
foreach($objItem in $colItems) {
$objInfo.Username= $objItem.UserName
$objInfo.ClientName = $objItem.Name
$objInfo.Manufacturer = $objItem.Manufacturer
$objInfo.Model = $objItem.Model
}
# Get workstation serial number from Win32_BIOS class.
$colItems = Get-WmiObject Win32_BIOS -Namespace "root\CIMV2" -ErrorAction stop -ComputerName $strComputer.name
foreach($objItem in $colItems) {
$objInfo.DevSerialNumber = $objItem.SerialNumber
}
#Get OS Info from Win32_OperatingSystem
$colItems = Get-WmiObject Win32_OperatingSystem -ErrorAction Stop -ComputerName $strComputer.name
foreach($objItem in $colItems) {
if ($objItem.OSArchitecture) {$objInfo.OSArchitecture = $objItem.OSArchitecture} else { $objInfo.OSArchitecture ="32 bit" }
$objInfo.Caption = $objItem.Caption
$objInfo.Version = $objItem.Version
$objInfo.RegisteredUser= $objItem.RegisteredUser
$objInfo.OsSerialNumber= $objItem.SerialNumber
}
#Get MS Windows Serial Number
#write-host $objInfo.Version
$objInfo.WindowsPK = Get-WindowsProductKey -Computername $strComputer.name -Version $objInfo.Version
#Get Office Version from WIn32_Product
$colItems = Get-WmiObject WIn32_Product -Computername $strComputer.name -Filter "Name like '%Office%'"| Where {($_.ProductID) }
foreach($objItem in $colItems) {
$objInfo.OfficeVersion = $objItem.Name
}
if ($objInfo.OfficeVersion) {
#Get Office Serial Number
$objInfo.OfficeSN = Get-MSOfficeProductKey -Computername $strComputer.name
}
else {
$objInfo.OfficeVersion = "Office not installed"
}
}
catch # If we get any error Reading computer data let's say it is Unreadable
{
$objInfo = New-Object PSObject | Select "ClientName", "OSArchitecture", "Username" ,"Manufacturer", "Model", "DevSerialNumber" ,"OfficeVersion", "OfficeSN", "Caption", "Version","RegisteredUser", "OSSerialNumber", "WindowsPK"
$objInfo.ClientName = $strComputer.name
$objInfo.OSArchitecture = 'Unreadable'
}
}
# If we are unable to connect let's say the computer is Unreachable
else
{
$objInfo = New-Object PSObject | Select "ClientName", "OSArchitecture", "Username" ,"Manufacturer", "Model", "DevSerialNumber" ,"OfficeVersion", "OfficeSN", "Caption", "Version","RegisteredUser", "OSSerialNumber", "WindowsPK"
$objInfo.ClientName = $strComputer.name
$objInfo.OSArchitecture = 'Unreachable'
}
# Add a new Row with current computer data
$NewCSVObject += $objInfo
$objInfo=""
}
# OutPut to CSV file
# If you want a video output too uncomment line below
$NewCSVObject |Out-GridView
$NewCSVObject | export-csv "$FilePath\ListPK_$(Get-Date -f yyyy-MM-dd).csv" -noType
# End of Script body
###################################################################
RispondiEliminaDownload Microsoft Office Keys 2014 working here
http://www.soulgaminghacks.com/microsoft-office-keys/
Wow that was strange. I just wrote an very long
RispondiEliminacomment but after I clicked submit my comment didn't show up.
Grrrr... well I'm not writing all that over again. Regardless, just wanted to
say superb blog!
Feel free to surf to my page castle clash hack password ()
Hi, I used this scrip and I' have some trouble. The column WindowsPK only show me BBBBB-BBBBB-BBBBB-BBBBB-BBBBB..... there something bad with Windows 7 because whith Windows XP works Ok!!! Thanks
RispondiEliminaExcellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking. office 2019 professional plus
RispondiEliminaI have read all the comments and suggestions posted by the visitors for this article are very fine,We will wait for your next article so only.Thanks! change control software
RispondiEliminaI have read all the comments and suggestions posted by the visitors for this article are very fine,We will wait for your next article so only.Thanks! All in one marketing platform
RispondiElimina