[C#] How to get Windows Product Key (Serial key)

Discussion in 'Mixed Languages' started by totalbot, Jan 30, 2011.

  1. totalbot

    totalbot MDL Novice

    Jan 30, 2011
    9
    1
    0
    I'm working on a little application, and on the main tab, I want the product key, like Windows Loader.

    But I cant figure how to get the key :s

    any idea guys? :)

    Thanks, Totalbot ^^


    -------------------

    Also, why I cant edit the OEMInformation registry keys with C# :eek:
     
  2. Calistoga

    Calistoga MDL Senior Member

    Jul 25, 2009
    421
    199
    10
    Check out this code :)
     
  3. totalbot

    totalbot MDL Novice

    Jan 30, 2011
    9
    1
    0
    well, is it only for xp?

    because I mainly need it for W7 :)
     
  4. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    #4 Alphawaves, Jan 31, 2011
    Last edited by a moderator: Apr 20, 2017
    From the link Calistoga gave i managed to get this, works ok in Windows 7

    Code:
    using System;
    using System.Collections;
    using Microsoft.Win32;
    
      namespace get_key
    {
        public partial class Form1 : Form
        {
    
     public Form1()
            {
                InitializeComponent();
            }
    
            public enum Key { Windows };
            public static byte[] GetRegistryDigitalProductId(Key key)
            {
                byte[] digitalProductId = null;
                RegistryKey registry = null;
                switch (key)
                {
                    // Open the Windows subkey readonly.
                    case Key.Windows:
                        registry =
                          Registry.LocalMachine.
                            OpenSubKey(
                              @"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
                                false);
                        break;
                }
                if (registry != null)
                {
                    // TODO: For other products, key name maybe different.
                    digitalProductId = registry.GetValue("DigitalProductId")
                      as byte[];
                    registry.Close();
                }
                return digitalProductId;
            }
            public static string DecodeProductKey(byte[] digitalProductId)
            {
                // Offset of first byte of encoded product key in 
                //  'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
                const int keyStartIndex = 52;
                // Offset of last byte of encoded product key in 
                //  'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
                const int keyEndIndex = keyStartIndex + 15;
                // Possible alpha-numeric characters in product key.
                char[] digits = new 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',
          };
                // Length of decoded product key
                const int decodeLength = 29;
                // Length of decoded product key in byte-form.
                // Each byte represents 2 chars.
                const int decodeStringLength = 15;
                // Array of containing the decoded product key.
                char[] decodedChars = new char[decodeLength];
                // Extract byte 52 to 67 inclusive.
                ArrayList hexPid = new ArrayList();
                for (int i = keyStartIndex; i <= keyEndIndex; i++)
                {
                    hexPid.Add(digitalProductId);
                }
                for (int i = decodeLength - 1; i >= 0; i--)
                {
                    // Every sixth char is a separator.
                    if ((i + 1) % 6 == 0)
                    {
                        decodedChars = '-';
                    }
                    else
                    {
                        // Do the actual decoding.
                        int digitMapIndex = 0;
                        for (int j = decodeStringLength - 1; j >= 0; j--)
                        {
                            int byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
                            hexPid[j] = (byte)(byteValue / 24);
                            digitMapIndex = byteValue % 24;
                            decodedChars = digits[digitMapIndex];
                        }
                    }
                }
                return new string(decodedChars);
            }  
        }
    }
    


    Usage:
    Code:
     byte[] results = Form1.GetRegistryDigitalProductId(Form1.Key.Windows);
    
                label1.Text = Form1.DecodeProductKey(results);
     
  5. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    #5 Alphawaves, Jan 31, 2011
    Last edited by a moderator: Apr 20, 2017
    Cant you use textbox's to add the information and apply from a button something like this:
    Code:
     Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "Model", textBox1.Text);
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "Manufacturer", textBox2.Text);
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "Logo", textBox3.Text);
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "SupportPhone", textBox4.Text);
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "SupportURL", textBox5.Text);
                Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "SupportHours", textBox6.Text);
    To get the value would be like this:
    Code:
     textBox1.Text = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "Model", "");
                textBox2.Text = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "Manufacturer", "");
                textBox3.Text = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "Logo", "");
                textBox4.Text = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "SupportPhone", "");
                textBox5.Text = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "SupportURL", "");
                textBox6.Text = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OEMInformation", "SupportHours", "");
    
    
    
    
    
    
     
  6. Calistoga

    Calistoga MDL Senior Member

    Jul 25, 2009
    421
    199
    10
    #6 Calistoga, Jan 31, 2011
    Last edited by a moderator: Apr 20, 2017
    Also, don't forget that your application needs to run elevated (administrator) to be able to write to HKEY_LOCAL_MACHINE. To make your app request such elevated privileges, you have to embed an Application Manifest.

    It works on all versions of Windows that places it's DigitalProductId in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
    Code:
    Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", false);
    Use the code posted by alphawaves, he has stripped away everything you don't need :) You can remove the switch (key) statement (but keep the case code) and the corresponding Key enum if you want.

    For maximum readability and reusability, you should pack all the code inside a separate class, for example class ProductKey { ... } , then have a static method, ex. ProductKey.GetLocalKey() - or something like that.
     
  7. jlgager

    jlgager MDL Developer

    Oct 30, 2009
    365
    3,230
    10
    Can someone add a visual basic .net version please with the ability to change the key as well. Thanks
     
  8. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    #8 Alphawaves, Jan 31, 2011
    Last edited by a moderator: Apr 20, 2017
    VB.NET:

    Add reference to system.management

    Install Key: Option 1 (Works better when called from a BackgroundWorker) this is from button:
    Code:
     Imports System.Management
    
    Dim failed As Boolean = False
    
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim key As String = TextBox1.Text
            Try
                Dim classInstance As New ManagementObject("root\CIMV2", "SoftwareLicensingService.Version='6.1.7600.16385'", Nothing)
                Try
                    Dim inParams As ManagementBaseObject = classInstance.GetMethodParameters("InstallProductKey")
                    inParams("ProductKey") = key
                    Dim outParams As ManagementBaseObject = classInstance.InvokeMethod("InstallProductKey", inParams, Nothing)
                Catch ex As System.Runtime.InteropServices.COMException
                    MessageBox.Show("Failed To Install Product Key", "Error")
                    failed = True
                    Exit Sub
                End Try
            Catch err As ManagementException
                failed = True
            End Try
            If failed = True Then
                MessageBox.Show("Failed To Install Product Key", "Error")
                Exit Sub
            End If
            Dim check As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM SoftwareLicensingProduct")
            For Each queryObj As ManagementObject In check.Get()
                Dim newkey As String = queryObj("PartialProductKey")
                If newkey = String.Empty Then
                Else
                    If key.Contains(newkey) = True Then
                        MsgBox("Installed Product Key: " & key & " Successfully")
                        Exit For
                    ElseIf key.Contains(newkey) = False Then
                        MsgBox("Failed to install: " & key & " .")
                        Exit For
                    End If
                End If
            Next
      End Sub
    Option 2:
    Code:
    Dim key As String = TextBox1.Text
            Dim SLMGR As New Process
            SLMGR.StartInfo.CreateNoWindow = True
            SLMGR.StartInfo.UseShellExecute = False
            SLMGR.StartInfo.RedirectStandardError = True
            SLMGR.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            SLMGR.StartInfo.FileName = "cscript"
            SLMGR.StartInfo.Arguments = (" //NOLOGO " & windir & "\System32\slmgr.vbs -ipk " & key)
            Me.Cursor = Cursors.WaitCursor
            SLMGR.Start()
            Do Until SLMGR.HasExited
                Application.DoEvents()
                System.Threading.Thread.Sleep(50)
            Loop
            Me.Cursor = Cursors.Default
    Read Key:
    Code:
    Public Function GetProductKey(ByVal KeyPath As String, ByVal ValueName As String) As String
    
            Dim HexBuf As Object = My.Computer.Registry.GetValue(KeyPath, ValueName, 0)
            If HexBuf Is Nothing Then Return "N/A"
            Dim tmp As String = ""
            For l As Integer = LBound(HexBuf) To UBound(HexBuf)
                tmp = tmp & " " & Hex(HexBuf(l))
            Next
            Dim StartOffset As Integer = 52
            Dim EndOffset As Integer = 67
            Dim Digits(24) As String
            Digits(0) = "B"
            Digits(1) = "C"
            Digits(2) = "D"
            Digits(3) = "F"
            Digits(4) = "G"
            Digits(5) = "H"
            Digits(6) = "J"
            Digits(7) = "K"
            Digits(8) = "M"
            Digits(9) = "P"
            Digits(10) = "Q"
            Digits(11) = "R"
            Digits(12) = "T"
            Digits(13) = "V"
            Digits(14) = "W"
            Digits(15) = "X"
            Digits(16) = "Y"
            Digits(17) = "2"
            Digits(18) = "3"
            Digits(19) = "4"
            Digits(20) = "6"
            Digits(21) = "7"
            Digits(22) = "8"
            Digits(23) = "9"
            Dim dLen As Integer = 29
            Dim sLen As Integer = 15
            Dim HexDigitalPID(15) As String
            Dim Des(30) As String
            Dim tmp2 As String = ""
            For i = StartOffset To EndOffset
                HexDigitalPID(i - StartOffset) = HexBuf(i)
                tmp2 = tmp2 & " " & Hex(HexDigitalPID(i - StartOffset))
            Next
            Dim KEYSTRING As String = ""
            For i As Integer = dLen - 1 To 0 Step -1
                If ((i + 1) Mod 6) = 0 Then
                    Des(i) = "-"
                    KEYSTRING = KEYSTRING & "-"
                Else
                    Dim HN As Integer = 0
                    For N As Integer = (sLen - 1) To 0 Step -1
                        Dim Value As Integer = ((HN * 2 ^ 8) Or HexDigitalPID(N))
                        HexDigitalPID(N) = Value \ 24
                        HN = (Value Mod 24)
                    Next
                    Des(i) = Digits(HN)
                    KEYSTRING = KEYSTRING & Digits(HN)
                End If
            Next
            Return StrReverse(KEYSTRING)
    
        End Function
    Usage:
    Code:
    TextBox1.Text = GetProductKey("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "DigitalProductId")
     
  9. totalbot

    totalbot MDL Novice

    Jan 30, 2011
    9
    1
    0
    Thanks for the informations everyone :):)
     
  10. jlgager

    jlgager MDL Developer

    Oct 30, 2009
    365
    3,230
    10
    Help! this stops working in C# if i switch to framework 3.5
     
  11. BobSheep

    BobSheep MDL Guru

    Apr 19, 2010
    2,330
    1,377
    90
    Any hints as to error messages, what it does or doesn't do, compile or run time exception?
     
  12. jlgager

    jlgager MDL Developer

    Oct 30, 2009
    365
    3,230
    10
    Sorry that wasn't descriptive at all, all the computers I try it on other than mine I get a System.NullReferenceException.
    Its in the Admin Toolkit 1.2 in the Activation section when you double click or click run. the error shows up in the textbox.
     
  13. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    #13 Alphawaves, Feb 19, 2011
    Last edited by a moderator: Apr 20, 2017
    Have you tried seeing if it works without this line in public void Activation():

    Code:
    throw new Exception();
     
  14. mictlan

    mictlan MDL Member

    Nov 9, 2009
    231
    116
    10
    Has someone ever looked at VL key retrieval, where key is not stored in registry?
     
  15. FreeStyler

    FreeStyler MDL Guru

    Jun 23, 2007
    3,557
    3,832
    120
    no where ...don't you think we would have manage to get it if it was possible?
     
  16. jlgager

    jlgager MDL Developer

    Oct 30, 2009
    365
    3,230
    10
    #16 jlgager, Oct 19, 2011
    Last edited by a moderator: Apr 20, 2017
    When i run this script in windows x64 bit "Byte[] digitalProductId" returns null. Thus I get a NullReferenceException error.
    When i run it in windows x86 the script runs correctly.

    Here is my code.
    Code:
    #region PRODUCT KEY
            /// <summary>
            /// Determines current Product Key.
            /// </summary>
            public static String ProductKey { get { return DecodeProductKey(GetRegistryDigitalProductId); } }
            private static Byte[] GetRegistryDigitalProductId
            {
                get
                {
                    try
                    {
                        byte[] digitalProductId = null;
                        RegistryKey registry = null;
                        registry = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", false);
    
                        if (registry != null)
                        {
                            digitalProductId = registry.GetValue("DigitalProductId") as byte[];
                            registry.Close();
                        }
                        return digitalProductId;
                    }
                    catch (Exception excep)
                    {
                        MessageBox.Show(excep.Message);
                        return null;
                    }
                }
            }
            private static String DecodeProductKey(Byte[] digitalProductId)
            {
                // Offset of first byte of encoded product key in 
                //  'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
                const int keyStartIndex = 52;
                // Offset of last byte of encoded product key in 
                //  'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
                const int keyEndIndex = keyStartIndex + 15;
                // Possible alpha-numeric characters in product key.
                char[] digits = new 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',
          };
                // Length of decoded product key
                const int decodeLength = 29;
                // Length of decoded product key in byte-form.
                // Each byte represents 2 chars.
                const int decodeStringLength = 15;
                // Array of containing the decoded product key.
                char[] decodedChars = new char[decodeLength];
                // Extract byte 52 to 67 inclusive.
                ArrayList hexPid = new ArrayList();
                for (int i = keyStartIndex; i <= keyEndIndex; i++)
                {
                    hexPid.Add(digitalProductId);
                }
                for (int i = decodeLength - 1; i >= 0; i--)
                {
                    // Every sixth char is a separator.
                    if ((i + 1) % 6 == 0)
                    {
                        decodedChars = '-';
                    }
                    else
                    {
                        // Do the actual decoding.
                        int digitMapIndex = 0;
                        for (int j = decodeStringLength - 1; j >= 0; j--)
                        {
                            int byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
                            hexPid[j] = (byte)(byteValue / 24);
                            digitMapIndex = byteValue % 24;
                            decodedChars = digits[digitMapIndex];
                        }
                    }
                }
                return new string(decodedChars);
            }
            #endregion PRODUCT KEY


    Please help as it is holding me up from finishing a library that I am about to publish here!
     
  17. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,170
    120
    #17 Josh Cell, Oct 19, 2011
    Last edited by a moderator: Apr 20, 2017


    Probably WOW64 Redirection ...

    You can make your APP in "Any CPU" achitecture ...
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  18. BobSheep

    BobSheep MDL Guru

    Apr 19, 2010
    2,330
    1,377
    90
    Change the build type from X86 to Any CPU (add if necessary).
     
  19. jlgager

    jlgager MDL Developer

    Oct 30, 2009
    365
    3,230
    10
    Thanks that fixed the problem! :)
     
  20. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,170
    120
    Yes, Welcome :)

    Well, this is code requires non-null signed values for decode de product key :)
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...