How to fast get Hardware-ID in C#?

117,697

Solution 1

For more details refer to this link

The following code will give you CPU ID:

namespace required System.Management

var mbs = new ManagementObjectSearcher("Select ProcessorId From Win32_processor");
ManagementObjectCollection mbsList = mbs.Get();
string id = "";
foreach (ManagementObject mo in mbsList)
{
    id = mo["ProcessorId"].ToString();
    break;
}

For Hard disk ID and motherboard id details refer this-link

To speed up this procedure, make sure you don't use SELECT *, but only select what you really need. Use SELECT * only during development when you try to find out what you need to use, because then the query will take much longer to complete.

Solution 2

I got here looking for the same thing and I found another solution. If you guys are interested I share this class:

using System;
using System.Management;
using System.Security.Cryptography;
using System.Security;
using System.Collections;
using System.Text;
namespace Security
{
    /// <summary>
    /// Generates a 16 byte Unique Identification code of a computer
    /// Example: 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9
    /// </summary>
    public class FingerPrint  
    {
        private static string fingerPrint = string.Empty;
        public static string Value()
        {
            if (string.IsNullOrEmpty(fingerPrint))
            {
                fingerPrint = GetHash("CPU >> " + cpuId() + "\nBIOS >> " + 
            biosId() + "\nBASE >> " + baseId() +
                            //"\nDISK >> "+ diskId() + "\nVIDEO >> " + 
            videoId() +"\nMAC >> "+ macId()
                                     );
            }
            return fingerPrint;
        }
        private static string GetHash(string s)
        {
            MD5 sec = new MD5CryptoServiceProvider();
            ASCIIEncoding enc = new ASCIIEncoding();
            byte[] bt = enc.GetBytes(s);
            return GetHexString(sec.ComputeHash(bt));
        }
        private static string GetHexString(byte[] bt)
        {
            string s = string.Empty;
            for (int i = 0; i < bt.Length; i++)
            {
                byte b = bt[i];
                int n, n1, n2;
                n = (int)b;
                n1 = n & 15;
                n2 = (n >> 4) & 15;
                if (n2 > 9)
                    s += ((char)(n2 - 10 + (int)'A')).ToString();
                else
                    s += n2.ToString();
                if (n1 > 9)
                    s += ((char)(n1 - 10 + (int)'A')).ToString();
                else
                    s += n1.ToString();
                if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-";
            }
            return s;
        }
        #region Original Device ID Getting Code
        //Return a hardware identifier
        private static string identifier
        (string wmiClass, string wmiProperty, string wmiMustBeTrue)
        {
            string result = "";
            System.Management.ManagementClass mc = 
        new System.Management.ManagementClass(wmiClass);
            System.Management.ManagementObjectCollection moc = mc.GetInstances();
            foreach (System.Management.ManagementObject mo in moc)
            {
                if (mo[wmiMustBeTrue].ToString() == "True")
                {
                    //Only get the first one
                    if (result == "")
                    {
                        try
                        {
                            result = mo[wmiProperty].ToString();
                            break;
                        }
                        catch
                        {
                        }
                    }
                }
            }
            return result;
        }
        //Return a hardware identifier
        private static string identifier(string wmiClass, string wmiProperty)
        {
            string result = "";
            System.Management.ManagementClass mc = 
        new System.Management.ManagementClass(wmiClass);
            System.Management.ManagementObjectCollection moc = mc.GetInstances();
            foreach (System.Management.ManagementObject mo in moc)
            {
                //Only get the first one
                if (result == "")
                {
                    try
                    {
                        result = mo[wmiProperty].ToString();
                        break;
                    }
                    catch
                    {
                    }
                }
            }
            return result;
        }
        private static string cpuId()
        {
            //Uses first CPU identifier available in order of preference
            //Don't get all identifiers, as it is very time consuming
            string retVal = identifier("Win32_Processor", "UniqueId");
            if (retVal == "") //If no UniqueID, use ProcessorID
            {
                retVal = identifier("Win32_Processor", "ProcessorId");
                if (retVal == "") //If no ProcessorId, use Name
                {
                    retVal = identifier("Win32_Processor", "Name");
                    if (retVal == "") //If no Name, use Manufacturer
                    {
                        retVal = identifier("Win32_Processor", "Manufacturer");
                    }
                    //Add clock speed for extra security
                    retVal += identifier("Win32_Processor", "MaxClockSpeed");
                }
            }
            return retVal;
        }
        //BIOS Identifier
        private static string biosId()
        {
            return identifier("Win32_BIOS", "Manufacturer")
            + identifier("Win32_BIOS", "SMBIOSBIOSVersion")
            + identifier("Win32_BIOS", "IdentificationCode")
            + identifier("Win32_BIOS", "SerialNumber")
            + identifier("Win32_BIOS", "ReleaseDate")
            + identifier("Win32_BIOS", "Version");
        }
        //Main physical hard drive ID
        private static string diskId()
        {
            return identifier("Win32_DiskDrive", "Model")
            + identifier("Win32_DiskDrive", "Manufacturer")
            + identifier("Win32_DiskDrive", "Signature")
            + identifier("Win32_DiskDrive", "TotalHeads");
        }
        //Motherboard ID
        private static string baseId()
        {
            return identifier("Win32_BaseBoard", "Model")
            + identifier("Win32_BaseBoard", "Manufacturer")
            + identifier("Win32_BaseBoard", "Name")
            + identifier("Win32_BaseBoard", "SerialNumber");
        }
        //Primary video controller ID
        private static string videoId()
        {
            return identifier("Win32_VideoController", "DriverVersion")
            + identifier("Win32_VideoController", "Name");
        }
        //First enabled network card ID
        private static string macId()
        {
            return identifier("Win32_NetworkAdapterConfiguration", 
                "MACAddress", "IPEnabled");
        }
        #endregion
    }
}

I won't take any credit for this because I found it here It worked faster than I expected for me. Without the graphic card, mac and drive id's I got the unique ID in about 2-3 seconds. With those above included I got it in about 4-5 seconds.

Note: Add reference to System.Management.

Solution 3

The following approach was inspired by this answer to a related (more general) question.

The approach is to read the MachineGuid value in registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography. This value is generated during OS installation.

There are few ways around the uniqueness of the Hardware-ID per machine using this approach. One method is editing the registry value, but this would cause complications on the user's machine afterwards. Another method is to clone a drive image which would copy the MachineGuid value.

However, no approach is hack-proof and this will certainly be good enough for normal users. On the plus side, this approach is quick performance-wise and simple to implement.

public string GetMachineGuid()
{
   string location = @"SOFTWARE\Microsoft\Cryptography";
   string name = "MachineGuid";

   using (RegistryKey localMachineX64View = 
       RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
   {
       using (RegistryKey rk = localMachineX64View.OpenSubKey(location))
       {
           if (rk == null)
               throw new KeyNotFoundException(
                   string.Format("Key Not Found: {0}", location));

           object machineGuid = rk.GetValue(name);
           if (machineGuid == null)
               throw new IndexOutOfRangeException(
                   string.Format("Index Not Found: {0}", name));

           return machineGuid.ToString();
       }
   }
}
Share:
117,697

Related videos on Youtube

guaike
Author by

guaike

Updated on March 01, 2022

Comments

  • guaike
    guaike about 2 years

    I need in my program to tie a license to a hardware ID. I tried use WMI, but it still slow.

    I need, for example, CPU, HDD, and motherboard info.

    • CodesInChaos
      CodesInChaos over 13 years
      Such a licensing scheme sounds more like an annoyance to the honest customer than a deterrence to a cracker.
    • Vinod Srivastav
      Vinod Srivastav almost 5 years
      Please see the answer here stackoverflow.com/a/50907399/3057246
  • Jens
    Jens about 14 years
    Be warned, though, that these ids are not neccesarily unique, or even existant. The processorID just identifies the processor design, the VolumeSerialnumber can be changed by the user and there are mainboard manufacturers that do not set a Serialnumber.
  • HotTester
    HotTester about 14 years
    The best way to generate a unique id is to make a id by combination of all of these id's i.e. cpu id, motherboard id and hard disk id.
  • guaike
    guaike about 14 years
    Thank you for your reply,But i think WMI still slow,do you have any other way with out WMI
  • Garo Yeriazarian
    Garo Yeriazarian over 13 years
    You say that WMI is slow, but how often do you run these checks? You only really need to check it at startup, then at random intervals from different places. If it's blocking your app, you can move the check to a background thread, just make sure you keep all the calls to the routines on the same thread and Dispose your objects appropriately (due to COM rules).
  • Fredrik
    Fredrik over 10 years
    the idea was to do it in C#
  • thelight
    thelight about 10 years
    @ Frederic - The original post shows that the ID is needed for a security (license) system. However, the code provided in the answers is reading the info from MS Windows. It is piece-a-cake to modify that information. However, the Hardware ID Extractor DLL gets the information directly from the CPU (hardware level). You cannot change the hardware ID of a CPU (unless you melt the CPU and rebuild it :) )
  • thelight
    thelight about 10 years
    Additionally it gets the information in less than 1 microsecond. While retrieving info from MS Windows takes up to 5 seconds!
  • thelight
    thelight about 10 years
    The DLL presented below retrieves the information in less than 1 microsecond.
  • thelight
    thelight about 10 years
    The original post shows that the ID is needed for a security (license) system. However, the code provided in the answers is reading the info from MS Windows. It is piece-a-cake to modify that information. However, the Hardware ID Extractor DLL gets the information directly from the CPU (hardware level). You cannot change the hardware ID of a CPU (unless you melt the CPU and rebuild it :) )
  • thelight
    thelight over 8 years
    @FredrikRedin - Can't C# import DLLs?
  • Roland
    Roland almost 8 years
    Not always - permission wise
  • GDS
    GDS almost 8 years
    I keep reading that there is no unique ID for processors (or any of the hardware) burned into the chips. How come this site claims that there is (and that they can retrieve it)?
  • Dan Is Fiddling By Firelight
    Dan Is Fiddling By Firelight almost 7 years
    Win10 gives warning that this might not be safe. Combined with screenshots from a Samsung utility, and the AV safe images being self-hosted not coming from a third party I'm concerned that even if this was a legit company at one point it may have gone rogue.
  • Server Overflow
    Server Overflow almost 7 years
    This is the scan from Google's VirusTotal.com. Only 3 (not-so-famous) antivirus products out of 62 shows a (false) positive alarm. All BIG (kaspersky, norton, panda, etc) av products shows the file clean. virustotal.com/en/file/…
  • ANeves
    ANeves over 6 years
    Benchmark: when my code uses Select * From Win32_processor it takes ~1s to run, when it uses Select ProcessorId From Win32_processor it takes ~0.01s!
  • Majid Sabzalian
    Majid Sabzalian over 6 years
    This Code is Nice. Tnq
  • NSGaga-mostly-inactive
    NSGaga-mostly-inactive over 6 years
    editing registry value is fast and not necessarily produces problems on the user machine - you can edit it, do what you want (in the s/w) and revert the value back.
  • bh_earth0
    bh_earth0 almost 6 years
    1)Nice.. 2) will this still generate Same ID if i use this code 1 or 2 month later?. Will this exclude removable usb hdd, usb wifi adpter, virtual network card by virtualization softwares ??
  • Germán Martínez
    Germán Martínez over 3 years
    After using this code for a while - there are issues: plugging in USB drives will change the key since it pulls info from any item with no empty value. Actually the whole identifier method is written badly and calling it multiple times for each property has to create the Management Class each time...
  • Lama
    Lama over 3 years
    not really useful, when you install bulk systems via OS images. You would have to manually set the GUID for each single machine.
  • LostPhysx
    LostPhysx about 3 years
    Will MaxClockSpeed change when it is overclocked?