However, being that I had a little free time and really like this code, I wanted to enhance it to make it more robust by adding a few extra things here and there. By doing this, you can see just how easy it is to take some existing code and modify it to meet your own specific requirements.

The list of items I wanted to add to the existing code are:

Run against multiple systems.

Allow this function to query remote systems; not just locally

Output an object instead of just text

In the object, show the following properties

Computername, ProductKey,OSDescription,OSVersion

Allow to query against 64bit systems

Error handling

Comment Based Help

First off, lets add some comment based help to this code:

function Get-ProductKey {
<#
.SYNOPSIS
Retrieves the product key and OS information from a local or remote system/s.
.DESCRIPTION
Retrieves the product key and OS information from a local or remote system/s. Queries of 64bit OS from a 32bit OS will result in
inaccurate data being returned for the Product Key. You must query a 64bit OS from a system running a 64bit OS.
.PARAMETER Computername
Name of the local or remote system/s.
.NOTES
Author: Boe Prox
Version: 1.1
-Update of function from http://powershell.com/cs/blogs/tips/archive/2012/04/30/getting-windows-product-key.aspx
-Added capability to query more than one system
-Supports remote system query
-Supports querying 64bit OSes
-Shows OS description and Version in output object
-Error Handling
.EXAMPLE
Get-ProductKey -Computername Server1
OSDescription Computername OSVersion ProductKey
------------- ------------ --------- ----------
Microsoft(R) Windows(R) Server 2003, Enterprise Edition Server1 5.2.3790 bcdfg-hjklm-pqrtt-vwxyy-12345
Description
-----------
Retrieves the product key information from 'Server1'
#>

I also add some parameters to the existing code with a default parameter value for the Computername to point to the local machine. I also add some aliases to support the ValueFromPipeLineByPropertyName which allows extra pipeline support. You will also notice that I set the type for Computername to [string[]] which means that it will take a collection of strings for that parameter.

I start off with a quick check to see if the system is reachable on the network and then perform a WMI query for some pieces of information regarding the Caption (Operating System name), Version and also the Architecture which will tell me if the OS is 64bit or 32bit which will be vital in determining what to do next for the product key.

The rest of the code deals with the actual operations to query the specified system’s registry key based on whether it is a 64bit system or 32bit. This is important because if the system is 64bit, the DigitalProductId4 key value must be used instead of DigitalProductId, otherwise you will not receive the accurate data for the product key. The other part of the code performs the translation of the value of the registry key to find the product key and also using a .Net class ([Microsoft.Win32.RegistryKey]) which will allow me to perform a remote query of the registry.

Lastly we need to make this into an object because this is PowerShell, after all. I use the New-Object cmdlet and supply a hash table of data that is saved to a variable. After the object is created, I opt to create a custom type name for this object to make it more unique which is then displayed to the user running the code.

Code in Action

Ok, lets run this against a local and remote system and see it in action.

Get-ProductKey -Computername Boe-PC,DC1

Whoops! Forgot to power on the server… Lets try this one more time!

Ok, that looks better. As you can see, not only is the product key displayed, but the computername as well as the Operating System and version are also displayed as well. This allows for better use of the code to see not only what the product key is, but what it also applies to as well.

57 Responses to Updating An Existing Get-ProductKey Function

30-40 2012R2 servers
You script gives us exact one ProductKey for all servers.
But! If we run slmgr /dlv on servers – this command gives us very different Partial Product Keys
And if we run some 3rd-party software to get these full keys – they are different than in step 2
How can it be?? Two different objects called “Product Key” ??? How we can resolve this issue??

The way this script is currently written it will not work on anything newer than Windows 7 and or 64bit. You can correct the script by replacing the try catch block that is actually doing the decoding with the following:

I have tested this on Windows Server 2012 R2 (and was actually able to install Windows Server 2012 R2 as a VM with the key that was returned), and I have tested this on Windows 10 which will return VK7JG-NPHTM-C97JM-9MPGT-3V66T which is a generic key that anybody who has Windows 10 will get when running a key finder on their machine, see http://www.maximumpc.com/microsoft-changes-rules-for-windows-10-activation-for-the-better/ for more information on that.

Thank you for providing the working try catch block. I attempted several of the other scripts I could find and I ended up with as many different and incorrect product keys. I was seriously considering a product key extractor third party tool until I modified the script with your try catch block. I have successfully tested the new script on two different systems Windows 8.1 Pro 64-bit and Windows 8.1 32-bit. Inside a VM I was able validate the modified script is getting the same results as iSunshare Product Key Finder.

I don’t understand what you mean by “Dot Sourcing” normally with these scripts I download them run them and then get my report. But with the product key script it just doesn’t return any data or reports when I run it.

Where did you get this?:
” This is important because if the system is 64bit, the DigitalProductId4 key value must be used instead of DigitalProductId, otherwise you will not receive the accurate data for the product key.”
Based on my tests this is not correct.
Using DigitalProductId4 always derive an icorrect Product Key

I know this is a pretty old post, but I’m confused. I enter a product key to activate windows, and it works. Then I run this script, and it returns a different value for the product key. What’s going on here?

When i run your script, the first one, i get no output. I am only trying to retrieve info off the local computer. I have tried . .\get-productkey, . .\get-productkey mycomputername, . .\get-productkey mycomputername, . .\get-productkey -computername mycomputername. I have also tried it without the dot sourcing. Please Advise.

Boe Prox, I’ve already come to see the Client UI but after I put in username and serve IP It can’t connect to the server, then the server-side PowerShell had the remind tips said BOB has disconnected from the server

OK, dot sourcing the script resolved this problem. You basically have to put a dot and then a space before the name of the script before you can run it successfully (. Get-ProductKey.ps1 and then run Get-ProductKey)

Now I am getting the wrong key though. I queried 3 different systems and they all came up with the same product key. Two of the systems were Windows 2008 R2 servers and one is a Windows 7 box.

I’m having some issues getting results from this. I have it running seemingly fine, and am passing it a list of computers from a file. It gets parsed ok, and since some of the names aren’t on the network currently, they come up ‘unreachable’ , which is to be expected. However, none of the other names that should be returning results actually are returning a key.

I get “Exception Callin…” in the Product Key column, and that’s it. Seems like it’s catching and truncating the exception to fit in my PS window, even when I output to a file via “| Out-File keys.txt”.

This is on remote machines. If I run it with just the local name it seems to get a key, however that is truncated as well.

Being rather new to the PS world, I’m not really sure how to prevent such truncating, nor what the exception might be likely to say. Any advice on this, or the Exception Calling problem?

Executing it bit by bit on a few different names yields the ‘Exception Callin..’ is likely ‘Exception calling “OpenRemoteBaseKey” with “2” argument(s): “The network path was not found”, which is a bit more descriptive of an error.

Having some issues running this. I have it running just fine, and am passing it a list of computers from a file. It gets parsed ok, and since some of the names aren’t on the network currently, they come up ‘unreachable’ , which is to be expected. However, none of the other names that should be returning results actually are returning a key.

I get “Exception Callin…” in the Product Key column, and that’s it. Seems like it’s catching and truncating the exception to fit in my PS window, which even when I output to a file via “| Out-File keys.txt”.

This is on remote machines. If I run it with just the local name it seems to get a key, however that is truncated as well.

Being rather new to the PS world, I’m not really sure how to prevent such truncating. Any advice on this, or the Exception Calling problem?

Hi Boe, thank you for all your hard work. I got this to work today in a domain environment but I am not sure why the Product Key is actually different than the license key on the box. Now, a product key finder will return the key on the box versus the Product Key that Get-ProductKey finds. Maybe I am missing something simple here, but are they supposed to be different?

Good night!
I ran the script correctly, the result is not correct.
Serial Key that returns is not the same one used to install the windows, tried on several platforms. A correction was made? Grateful, Fabricio Paim

Hi, I have run your script on windows 7 64bit as “PS C:\Scripting> .\Get-ProductKey.ps1” and I get no report back. Tried it with -Computername… and still got no results. I have also tried it on other windows 7 32bit comps and did not receive any results.

Hmmm… When running against 64 bit systems, you need to make sure that you are running it from a 64 bit system. Also, while I don’t think it should matter, are you also running it from an Administrator prompt (run as administrator)?

Hi, I do not understand this – at 8 July I not download script – after accept licence agreement at MS Script Repository is nothing happen (not action for file download). but today is working…
thanks for you script I test …