|
Some time ago I wrote up a short article here on how to
use P/Invoke to use one of the Kerne32 APIs to get the Volume Serial Number
off the specified hard drive. It turns out that there has been some feedback
on this and related subjects and so I've decided to revisit it.
The whole concept of "per machine" or "per
seat" software licensing has tended to revolve around unique machine
keys, dongles and other ways of tying a licensing scheme to a particular
machine (or machines). Microsoft uses this in its "per seat"
or "per processor" licensing scheme as do many other vendors.
The Activation key used for Windows XP and Windows Server is also based
on a composite of hardware - based "IDs".
Most all of these can be easily obtained through the
use of the Windows Management Instrumentation classes in the System.Managment
namespace, through instances of the ManagementObject class.
I'm not giving a tutorial on how to use these classes
here; the MSDN documentation is fairly complete. We get lots of questions
(usually but not always from newbies) from people who haven't yet learned
Rule Number One of software development: RTFM. And of
course, our advice, taking the meaning of the great Chinese proverb about
teaching men to fish, is usually "RTFM!" (sometimes with a handy
link to the actual place where the solution to the question or problem
can be found). I say this seriously because it surprises me how many people
have not invested the time to learn how to search on their own for answers.
You have your Visual Studio.NET help built in where all you have to do
is highlight the item and hit F1 to search the index, and you have a built-in
search window too (which by the way accepts boolean modifiers). For those
without Studio, you have the Framework SDK help which works the same way.
Then, you have MSDN online with a huge searchable archive of Knowlege
Base articles, help documentation and articles. Finally, you have Google,
arguably the best web search engine ever invented, and all you need to
do is learn the syntax for complex searches. Switch to the "Groups"
tab and you can repeat your search on their 20 year history of all newsgroups.
I think you get the picture.
Probably the most useful of all of the methods I've created
below is the one to retrieve the CPU ID, since this is the one piece of
hardware that almost never changes. If you reformat your hard drive, your
Volume Serial Number will be changed. As well, there are a number of program
utilities that allow you to change the HD volume serial without reformatting
the drive. Same with NICs- the network card in my machine now is not the
same one that I had in there a year ago. However, the CPU is the same.
I've put together a class library with what you see below,
along with a nice Winforms - based test harness for it, and you can download
the VS.NET 2003 solution for it at the bottom of this article. Enjoy!
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Management;
namespace MachineInfo
{
public class GetInfo
{
/// <summary>
/// return Volume Serial Number from hard drive
/// </summary>
/// <param name="strDriveLetter">[optional] Drive letter</param>
/// <returns>[string] VolumeSerialNumber</returns>
public string GetVolumeSerial(string strDriveLetter)
{
if( strDriveLetter=="" || strDriveLetter==null) strDriveLetter="C";
ManagementObject disk =
new ManagementObject("win32_logicaldisk.deviceid=\"" + strDriveLetter +":\"");
disk.Get();
return disk["VolumeSerialNumber"].ToString();
}
/// <summary>
/// Returns MAC Address from first Network Card in Computer
/// </summary>
/// <returns>[string] MAC Address</returns>
public string GetMACAddress()
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
string MACAddress=String.Empty;
foreach(ManagementObject mo in moc)
{
if(MACAddress==String.Empty) // only return MAC Address from first card
{
if((bool)mo["IPEnabled"] == true) MACAddress= mo["MacAddress"].ToString() ;
}
mo.Dispose();
}
MACAddress=MACAddress.Replace(":","");
return MACAddress;
}
/// <summary>
/// Return processorId from first CPU in machine
/// </summary>
/// <returns>[string] ProcessorId</returns>
public string GetCPUId()
{
string cpuInfo = String.Empty;
string temp=String.Empty;
ManagementClass mc = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = mc.GetInstances();
foreach(ManagementObject mo in moc)
{
if(cpuInfo==String.Empty)
{// only return cpuInfo from first CPU
cpuInfo = mo.Properties["ProcessorId"].Value.ToString();
}
}
return cpuInfo;
}
}
}
|
I want to add before closing that you can gain access to these objects
through plain old VBScript in a VBS file:
Function CpuID()
Dim oWMI, oCpu
Set oWMI = GetObject("winmgmts:")
For Each oCpu in oWMI.InstancesOf("Win32_Processor")
wscript.echo "CPU: " & oCpu.ProcessorID
Next
End Function
CpuID |
Download
the code that accompanies this article
| Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform. Pete's samples at GotDotNet.com have been downloaded over 41,000 times. You can read Peter's UnBlog Here. --><-- NOTE: Post QUESTIONS on FORUMS! |  |
Do you have a question or comment about this article? Have a programming problem you need to solve? Post it at eggheadcafe.com forums and receive immediate email notification of responses.
|