Retrieving Non-Volatile USB Serial Number Using C# .NET

The problem all stems from the fact that the USB specification does not require a hard coded serial number as mandatory for USB devices, especially memory sticks although in my tests 99% of sticks did in fact have an OEM serial number.

2007-01-24 20:01:00.0

Retrieving Non-Volatile USB Serial Number Using C# .NET

This is something I meant to post up ages ago as information and solutions are hard to come by on this specific topic.

The problem all stems from the fact that the USB specification does not require a hard coded serial number as mandatory for USB devices, especially memory sticks although in my tests 99% of sticks did in fact have an OEM serial number.

Windows secifies its own serial number for each device which is volatile meaning the serial number is erased and renewed everytime the USB stick is formatted. This causes problems when your using your stick as a security device or dongle. Basically, in Windows if you get 2 devices from the same manufacturer without OEM numbers, it gets confused. Not sure about a Mac or Linux.

Anyways, to the point of this article.....how do we actually get the OEM serail so a device can be formatted over and over again and you can still tell the drive apart from another one?

Well, there are 2 ways. Using the registry or using something called a Win32 WMI Provider. WMI is a database of all aspects of your operating system and hardware and is used by Windows to hold everything together. Infact the WMI is a all held in the regisrty but the provider using management classes lets you query it using SQL.

You need to add a reference to your C Sharp program to SYSTEM.MANAGEMENT.

Step 1 is to query the Win32_LogicalDiskToPartition section and get all the logical disk names e.g: F:\ and mapped enumeration which have a big long string attached like so : 000000001

This will give us the enumeration of the drive so we can then strip off the int at the end and query the Win32_DiskDrive. The drive we are looking for will be in the form \\\\.\\PHYSICALDRIVE(enumeration(enumeration) where (enumeration) is the bit we found out above. The PNPDeviceID is the full non-volatile serial number which with a bit of parsing we can retrieve the actual serial number.

It may sound confusing reading the above so the best thing to do is look at the attached source. I have wrapped it all up into a class that can be called as follows:

USBSerialNumber usb = new USBSerialNumber();
string serial = usb.getSerialNumberFromDriveLetter("f:\"Wink;
MessageBox.Show(serial);

You can download the class by clicking the image below:

Download USBSerialNumber Class

Hope you like it and it saves you some time!

UPDATE Thursday 10th May 2007
You can download a test project from here : USBSerialNumberTest.zip

Tags: .NET | My Work
Add to your del.icio.us    DIGG This!    Technorati Cosmos Link    Post to Reddit    Add to your Furl    Add to Blinklist
Comments [22] - Leave a comment

Comments

Anil said:
thanks yaar...
it working but can you give me some idea that in vc how can we get serial number for removal drive
Hyunseok said:
Hey, Thanks. I was looking for this. And it works fine. Thanks again
Kevin said:
I get the following error. Maybe I have placed the class file incorrectly into my project. Can you offer some guidance?

The type or namespace 'USBSerialNumber' could not be found(are you missing a directive or an assembly reference?)

I'm using VS 2005.
Dan said:
Hi Kevin, if you add the class to your project (Existing item) then you will have to reference it as:

USBSerialNumber.USBSerialNumber usb = new USBSerialNumber.USBSerialNumber();
string serial = usb.getSerialNumberFromDriveLetter("f:";
MessageBox.Show(serial);

You could rename the namespace in the class to the same as your project also.

Dan.
Kevin said:
This seemed to work, except I'm not getting the serial in my textbox. Any thoughts?

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
USBDriveSerialNumber.USBSerialNumber usb = new
USBDriveSerialNumber.USBSerialNumber();
string serial = usb.getSerialNumberFromDriveLetter("F:\");
this.textBox1.Text = serial;
}
Dan said:
I'll post up a downloadable project for other people soon but Kevin, if you send me your project zipped, I'll have a look. Dan.
Kevin said:
One more quick question, and I'll leave you alone. Can I get the Harddrive serial with this as well? If so, what would I need to add to make that happen? I would rather utilize this code, if possible, than add yet another class to do this.
Dan said:
Hi Kevin, you can get the hardware serial easily enough using the built in .net api functions. This class deals specifically with USB devices to get the real serial number. Harddrives themselves dont have this issue so the serial you get from c# is the one you need.
Jose Lozano said:
some form to apply it in ActionScript (flash)?
SecureBT said:
Be carefull that this method will fail if the USB device is mounted in a directory (mount point) without any drive letter assigned. See FindFirstVolumeMountPoint(...) API for more information
SecureBT said:
In response to the question of Kevin 'Can I get the Harddrive serial with this as well?', the answer is yes but it is a bit more complicated. In fact, a driver letter as 'C:' can span on multiple partitions and so, on multiple disk. XP with NTFS allow the creation of RAID like disk (see disk management for more information). In conlusion, if you use WMI to retrieve the serial number of disk from a driver letter, you can get more than one serial number (I think that the maximum is 32).

Thank to Daniel Mackey to show the power of the unfortunaly unknowned WMI.
mantissa said:
superbly useful tip - thanks Dan!
Nick said:
FYI, this code seems to require that the user have admin permissions, otherwise no information is returned, no errors either.

http://www.msdner.com/dev-archive/160/12-44-1601927.shtm

"A support request has confirmed through the WMI dev team: Win32_DiskPartition query requires elevated rights. No Exception is raised, just returns as if no Partition exists."
Roy said:
Thank you for this lovely post; I'ld like to ask:
is there any way to Deny or Grant the hard reset for a user on a PDA? (I mean like switching it On/OFF)

if no way to do the above, can I store an application in a Non-Volatile memory, and AutoStart the application even after a Hard reset?
DougRoss said:
Thanks for the code, however I have a question. PHPDeviceID will provide a non volatile id with the last number being a manufacturer's serial number, if the manufacturer leaves one on the device. If the manufacturer does not write one on the device, then Windows XP at least seems to generate one that is unique only to a USB port on whatever computer you are on. i.e. if you plug the same USB key into 2 ports on the same computer you will get 2 different PNPDeviceID strings... Do you know if there is any way to capture that the manufacturer's serial number is actually blank, as I would like to prompt the user that this particular USB key cannot be used as a unique device. cheers Doug
Vidura said:
hi friend thanks a lot for the source code and all. it helps me a lot

i'd like to ask is there a way to get-rid of searching from the floppy. becos everytime when searching the floppy drive bulb flashing on. is there a way to stop that....

hope a reply from you.
Thanks in Advance........ :-)
Yen said:
Hi thx for the code sharing... i'v another question is it possible to read partition table/boot sector of storage device by using C#? Thank you!!!
vidura sumedha silva said:
Thanks and keep up the good works!
Thanks for shairing the knowledge. thats is a act of a god.
oceana said:
could u give the same code in vb.60
or a c# dll that can be used in vb.60
Vibhu said:
Hi Dan,
Thank u Soooooooooooooooooooo Muchhhhhh for your code.
It Really helped me .
Warm Regards
Vibhu
devliker said:
FYI, this code seems to require that the user have admin permissions, otherwise no information is returned, no errors either.

http://www.msdner.com/dev-archive/160/12-44-1601927.shtm

"A support request has confirmed through the WMI dev team: Win32_DiskPartition query requires elevated rights. No Exception is raised, just returns as if no Partition exists."

msdner.com is move to www.itags.org
Bambang Piscesa said:
Thanks A Lot for your code. It is working well and help me a lot... ^^