Archive

Archive for June, 2012

What is the best unique computer identifier?

June 28th, 2012 2 comments

I have been trying to find out what is the best way to uniquely identify a computer for licensing purposes.

Here are some suggestions.

Computer SID

In a previous post “Read computer sid on 64-bit machine” I show how to get the Product ID of the operating system as the unique identifier.

Cons
This seemed great and I even used it for a licensing tool until I installed the software on multiple virtual machines!
The VM’s were cloned from the same base image and guess what? They all had the same Product ID, which meant that every computer passed in the same ID.

Network Card Mac address and other hardware items

These do provide a level of uniqueness but there are a few problems:

Cons

  1. Most computers these days have many network cards, USB wi-fi etc, so which card do you choose to get the MAC address from?
  2. Unless it’s in a laptop or onboard, NIC’s can easily be replaced.

What is the best unique computer identifier

Thinking logically you want to use an identifier that is likely to change the least so CPU’s, NIC’s, Hard Drives etc etc should all be rejected.

The one component that generally doesn’t change very often is the motherboard. The motherboard has a UUID (Univerally Unique Identifier), that can be read from the bios.

This value is unique in both physical computers and Virtual Machines.

The following code sample is a c# example of how to read the UUID from the motherboard BIOS using the System.Management.ManagementClass to read the Win32_ComputerSystemProduct

using System.Management;
...
...
public static string UUID
{
    get
    {
        string uuid = string.Empty;

        ManagementClass mc = new ManagementClass("Win32_ComputerSystemProduct");
        ManagementObjectCollection moc = mc.GetInstances();

        foreach (ManagementObject mo in moc)
        {
            uuid = mo.Properties["UUID"].Value.ToString();
            break;
        }

        return uuid;
    }
}

Note for a full reference of all the Win32 Management classes go here:
MSDN Win32 Classes

VN:F [1.9.22_1171]
Rating: 9.7/10 (11 votes cast)

Categories: c#, Code Tags:

How to read computer SID on 64-bit machine

June 26th, 2012 1 comment

To get a unique identifier for a computer the recommended key is “ProductId” that is accessible from the following registry key – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion.

This is the value you see as “Product ID” on the properties screen of your computer.

To access this key can be a little problematic if you are attempting to read the “ProductId” sub-key on a 64-bit machine from a 32-bit application.

This is due to Registry Reflection or WOW64 as it is sometimes called.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa384235%28v=vs.85%29.aspx

In short the 64-bit OS shows 2 logical views of certain portions of the registry on WOW64, one for 32-bit and one for 64-bit. In the case of the “ProductId” key it explicitly exists in the 64-bit view so the following code will fail to find the key, as when running inside the 32-bit application it accesses the 32-bit view of the registry and fails to find the key.

The following code will return an empty string

public static string ComputerSID
{
    get
    {
        string sid = string.Empty;

        string SIDKey = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
        RegistryKey key = Registry.LocalMachine.OpenSubKey(SIDKey);

        object keyValue = key.GetValue("ProductId");

        if (keyValue != null)
        {
            sid = keyValue.ToString();
        }

        key = null;
        keyValue = null;

        return sid;
    }
}

To make this work you have to explicitly request c# to open the 64-bit view of the registry.
The following code sample will work.

public static string ComputerSID
{
    get
    {
        string sid = string.Empty;
        string SIDKey = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";

        RegistryKey baseKey = null;
        if (Environment.Is64BitOperatingSystem)
        {
            baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
        }
        else
        {
            baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
        }

        RegistryKey key = baseKey.OpenSubKey(SIDKey);

        object keyValue = key.GetValue("ProductId");

        if (keyValue != null)
        {
            sid = keyValue.ToString();
        }

        key = null;
        keyValue = null;

        return sid;
    }
}

Cheers
John

VN:F [1.9.22_1171]
Rating: 5.5/10 (2 votes cast)

Categories: c#, Code Tags: