C# Creating a unique ID based on hardware ids

12,312

Solution 1

Here is a pretty decent article about how MS did it with Windows XP. Maybe not exactly what you're looking for, but it's a great jumping-off point.

Windows XP Activation Explained

What hardware does Windows check?

The system checks these ten categories of hardware:

  • Display Adapter
  • SCSI Adapter
  • IDE Adapter (effectively the motherboard)
  • Network Adapter (NIC) and its MAC Address
  • RAM Amount Range (i.e., 0-64mb, 64-128mb, etc.)
  • Processor Type
  • Processor Serial Number
  • Hard Drive Device
  • Hard Drive Volume Serial Number (VSN)
  • CD-ROM / CD-RW / DVD-ROM

Solution 2

Not really an answer, but a word of caution. I worked for a software company that did a similar sort of licensing mechanism and it was... brittle. Especially on laptops. Consider:

  1. When switching between wired and wireless on a laptop, you'll have a different MAC address on each interface.

  2. There may be advantages to changing your MAC address. eg, some cable internet providers in the states foolishly tie your MAC address to your account and one might need to plug their computer in straight to the cable modem and then clone their router's MAC if their router were to die.

  3. If a user were to boot from a different hard drive (for example, a flash drive or a USB stick), would this change what's reported as the first drive?

And this was long before the days of commodity virtualization. Now consider that you can switch a setting and reboot your VM and have: a different amount of RAM, a different sized hard drive, a different type of virtual hard drive controller type (IDE, SCSI, perhaps multiple SCSI controller interfaces). And you can hot-swap CD/DVD devices and change NIC settings with a mouse click.

So I'm not saying "don't do this", exactly, but I will encourage you to test this mechanism on as many machines in as many environments as you can, and I will further suggest that your users will have precious little patience when they can't run the software that they've paid for.

Have you considered hardware dongles?

Solution 3

I've found that the MAC address isn't really worth checking nowadays. Every computer has more than one network adapter, any one of them might be an external device that may or may not be present at any given time. We rolled out a system that paid too much attention to MAC address years ago, and it ended up being a customer service disaster.

On the other hand, it's relatively rare to swap out your CPU, motherboard, bus/disk controllers, or the main hard drive.

Share:
12,312
ErocM
Author by

ErocM

Updated on June 03, 2022

Comments

  • ErocM
    ErocM almost 2 years

    I am creating a license that is specific to a machine. The license is based on the following items:

    1. MAC Address
    2. CPU Serial Number
    3. Computer Volume Serial Number of drive0

    I am assuming that if 2 of the 3 match, then my license is valid. So, the can get a new network card, and the license is still valid, etc.

    Is this a good approach or am I going to have issues with this not matching or changing regularly?

    I'm trying to get a unique identifier for the computer so that I can validate the license.

    Please let me know how this looks or if you have a better solution!

    Thanks again!

    ** HERE IS WHAT I CAME UP WITH **

    I ended up only using the VolumeSerial, CpuId, and VideoControllerDescription.

        public enum HardwareProfileComponents
        {
            ComputerModel,
            VolumeSerial,
            CpuId,
            MemoryCapacity,
            VideoControllerDescription
        }
    
        public static Dictionary<string, string> HardwareProfile()
        {
            var retval = new Dictionary<string, string>
                             {
                                 {HardwareProfileComponents.ComputerModel.ToString(), GetComputerModel()},
                                 {HardwareProfileComponents.VolumeSerial.ToString(), GetVolumeSerial()},
                                 {HardwareProfileComponents.CpuId.ToString(), GetCpuId()},
                                 {HardwareProfileComponents.MemoryCapacity.ToString(), GetMemoryAmount()},
                                 {HardwareProfileComponents.VideoControllerDescription.ToString(), GetVideoControllerDescription()}
                             };
            return retval;
    
        }
    
        private static string GetVideoControllerDescription()
        {
            Console.WriteLine("GetVideoControllerDescription");
    
            var s1 = new ManagementObjectSearcher("select * from Win32_VideoController");
            foreach (ManagementObject oReturn in s1.Get())
            {
                var desc = oReturn["AdapterRam"];
                if ( desc == null) continue;
                return oReturn["Description"].ToString().Trim();
            }
            return string.Empty;
        }
    
    
        private static string GetComputerModel()
        {
            Console.WriteLine("GetComputerModel");
            var s1 = new ManagementObjectSearcher("select * from Win32_ComputerSystem"); 
            foreach (ManagementObject oReturn in s1.Get())
            {
                return oReturn["Model"].ToString().Trim();
            }            
            return string.Empty;
        }
    
        private static string GetMemoryAmount()
        {
            Console.WriteLine("GetMemoryAmount");
            var s1 = new ManagementObjectSearcher("select * from Win32_PhysicalMemory");
            foreach (ManagementObject oReturn in s1.Get())
            {
                return oReturn["Capacity"].ToString().Trim();
            }
            return string.Empty;
        }
    
        private static string GetVolumeSerial()
        {
            Console.WriteLine("GetVolumeSerial");
            var disk = new ManagementObject(@"win32_logicaldisk.deviceid=""c:""");
            disk.Get();
    
            string volumeSerial = disk["VolumeSerialNumber"].ToString();
            disk.Dispose();
    
            return volumeSerial;
        }
    
        private static string GetCpuId()
        {
            Console.WriteLine("GetCpuId");
            var managClass = new ManagementClass("win32_processor");
            var managCollec = managClass.GetInstances();
    
            foreach (ManagementObject managObj in managCollec)
            {
                //Get only the first CPU's ID
                return managObj.Properties["processorID"].Value.ToString();
            }
            return string.Empty;
        }
    
  • ErocM
    ErocM about 12 years
    This gave me what I was looking for. More of a solid list of things I can use. I am going to pick items that would not normally change on a given day. Thank you!
  • ErocM
    ErocM about 12 years
    I printed this and discussed it with the programmers and my boss wants us to see what I can do with items that do not typically change. I can only vote for one but I did give you a mark up for a good answer and things to keep an eye out for.
  • Wesley Long
    Wesley Long about 12 years
    No problem. I'm glad I could help. BTW - I was looking at the same issue for something I'm working on. After reading the other comments and answers, I believe I will "skip" the NIC MAC address. Edward and Sean both offered sage advice in that arena.
  • ErocM
    ErocM about 12 years
    Great comment on the MAC address. I completely agree. I have a removable network adapter for my latop and it broke right off. I am using the CPU serial number and hard drive serial (based off the c drive). When I tried to get the motherboard serial, on half the computers I tested, I got back blanks. Did the same happen with you?
  • amarnath chatterjee
    amarnath chatterjee about 8 years
    CPU, motherboard, bus/disk controllers etc... these serial numbers are either same or blank ... anybody else faced the same problem ?