This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to get serial number of USB-Stick in C#
Does anybody have any suggestions, preferably something that would work across windows 7 and xp, I already tried the class posted here http://www.cfdan.com/posts/Retrieving_Non-Volatile_USB_Serial_Number_Using_C_Sharp.cfm however a serial number is never returned.
I understand that the serial number on a usb is optional but I have tried 3 separate usb sticks so I doubt this is the problem.
From this post:
ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
foreach (ManagementObject currentObject in theSearcher.Get())
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}
Related
This question already has answers here:
How to get client's computer name
(3 answers)
Closed 7 months ago.
The community reviewed whether to reopen this question 7 months ago and left it closed:
Original close reason(s) were not resolved
There is any way to get the PC Name of a client Machine in web application, who is working in different Network, in c# asp.net ?
"This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server. showing this error.
By doing the answer given in this
How to get client's computer name ,
I think this will help you:
string clienIp = Request.UserHostName;
string computenMame = CompName(clientIp);
public static string CompName(string clienIp)
{
IPAddress myIP = IPAddress.Parse(clienIp);
IPHostEntry GetIPHost = Dns.GetHostEntry(myIP);
List<string> compName =
GetIPHost.HostName.ToString().Split('.').ToList();
return compName.First();
}
Answers to the question "How to get a list of all cameras (USB, IP, build-in) for capture" are all answered by pointing to DirectShowNet.
However all these entries (here's the most prominent example) I could find are several years old, the library itself seems quite a bit old. Therefore my rather simple question: is the a better, more convenient way now, or is this still the way to go?
After searching around this topic in different forums, I found that using WMI is the best approach to solve this.
With the help of this article I managed to adapt code snippets to the following simple method, which works perfectly in my case:
/// <summary>
/// uses WMI to get all available cameras and add them to the list
/// </summary>
private void GetAvailableCameraList()
{
AvailableCameras = new List<string>();
string wmiQuery = string.Format("SELECT * FROM Win32_PnPSignedDriver");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery);
ManagementObjectCollection retObjectCollection = searcher.Get();
foreach (var WmiObject in retObjectCollection)
{
if (WmiObject["DeviceClass"] != null && WmiObject["DeviceClass"].ToString().Equals("IMAGE"))
{
AvailableCameras.Add(WmiObject["DeviceName"].ToString());
}
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WIN32_Processor::Is ProcessorId Unique for all computers
I'm creating an application with a trial feature. To detect if a certain user already used a trial the application connects to my server with their machineHash.
The machineHash function look like this:
string cpuInfo = string.Empty;
ManagementClass mc = new ManagementClass("win32_processor");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
if (cpuInfo == "")
{
//Get only the first CPU's ID
cpuInfo = mo.Properties["processorID"].Value.ToString();
break;
}
}
return cpuInfo;
However, it does report my processor ID as BFEBFBFF000206A7 (on two different Intel machines, i5 and a Celeron). Googling BFEBFBFF000206A7 has hits too, so it's not unique.
Could anyone tell me why this is not unique? I don't want to use the VolumeSerial of let's say the C:\ drive as that can be easily changed with a simple command.
Instead of using the processor ID, combine multiple ID's of a system into 1 string to compare each time the program sends check.
Use something like this:
using System.Management;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"select * from " + whatever_id);
All the values you can replace whatever_id with can be found here:
http://www.codeproject.com/Articles/17973/How-To-Get-Hardware-Information-CPU-ID-MainBoard-I
I would find a few you want to use, some of which can be unique, but even if you dont use a unique field, you can make combinations that will, for most intents and purposes, be unique.
I know there are a number of similar questions in stackoverflow such as the followings:
What's a good way to uniquely identify a computer?
What is a good unique PC identifier?
Unique computer id C#
WIN32_Processor::Is ProcessorId Unique for all computers
How to uniquely identify computer using C#?
... and dozens more and I have studied them all.
The problem is that some of the accepted answers have suggested MAC address as an unique identifier which is entirely incorrect. Some other answers have suggested to use a combination of various components which seems more logical. However, in case of using a combination it should be considered which component is naturally unlikely to be changed frequently. A few days ago we developed a key generator for a software licensing issue where we used the combination of CPUID and MAC to identify a windows pc uniquely and till practical testing we thought our approach was good enough. Ironically when we went testing it we found three computers returning the same id with our key generator!
So, is there really any way to uniquely identify any computer at all? Right now we just need to make our key generator to work on windows pc. Some way (if possible at all) using c# would be great as our system is developed on .net.
Update:
Sorry for creating some confusions and an apparently false alarm. We found out some incorrectness in our method of retrieving HW info. Primarily I thought of deleting this question as now my own confusion has gone and I do believe that a combination of two or more components is good enough to identify a computer. However, then I decided to keep it because I think I should clarify what was causing the problem as the same thing might hurt some other guy in future.
This is what we were doing (excluding other codes):
We were using a getManagementInfo function to retrieve MAC and Processor ID
private String getManagementInfo(String StrKey_String, String strIndex)
{
String strHwInfo = null;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + StrKey_String);
foreach (ManagementObject share in searcher.Get())
{
strHwInfo += share[strIndex];
}
}
catch (Exception ex)
{
// show some error message
}
return strHwInfo;
}
Then where needed we used that function to retrieve MAC Address
string strMAC = getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress");
and to retrieve ProcessorID
string strProcessorId = getManagementInfo("Win32_Processor", "ProcessorId");
At this point, strMAC would contain more than one MAC address if there are more than one. To take only one we just took the first 17 characters (12 MAC digits and 5 colons in between).
strMAC = strMAC.Length > 17 ? strMAC.Remove(17) : strMAC;
This is where we made the mistake. Because getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress") was returning a number of extra MAC addresses that were really in use. For example, when we searched for MAC addresses in the command prompt by getmac command then it showed one or two MAC addresses for each pc which were all different. But getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress") returned four to five MAC addresses some of which were identical for all computers. As we just took the first MAC address that our function returned instead of checking anything else, the identical MAC addresses were taken in strMAC incidently.
The following code by Sowkot Osman does the trick by returning only the first active/ enabled MAC address:
private static string macId()
{
return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled");
}
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;
}
However, I was absolutely right about the identical Processor ID issue. All three returned the same Processor ID when we put wmic cpu get ProcessorId command in their command prompts.
Now we have decided to use Motherboard serial number instead of Processor ID to make a combination with MAC address. I think our purpose will be served with this way and if it doesn't in some cases then we should let it go in those few cases.
How about adding motherboard serial number as well e.g.:
using System.management;
//Code for retrieving motherboard's serial number
ManagementObjectSearcher MOS = new ManagementObjectSearcher("Select * From Win32_BaseBoard");
foreach (ManagementObject getserial in MOS.Get())
{
textBox1.Text = getserial["SerialNumber"].ToString();
}
//Code for retrieving Processor's Identity
MOS = new ManagementObjectSearcher("Select * From Win32_processor");
foreach (ManagementObject getPID in MOS.Get())
{
textBox2.Text = getPID["ProcessorID"].ToString();
}
//Code for retrieving Network Adapter Configuration
MOS = new ManagementObjectSearcher("Select * From Win32_NetworkAdapterConfiguration");
foreach (ManagementObject mac in MOS.Get())
{
textBox3.Text = mac["MACAddress"].ToString();
}
The fact in getting a globally unique ID is, only MAC address is the ID that will not change if you set up your system all over. IF you are generating a key for a specific product, the best way to do it is assigning unique IDs for products and combining the product ID with MAC address. Hope it helps.
I Completely agree with just the above comment.
For Software licensening, you can use:
Computer MAC Address (Take all if multiple NIC Card) + Your software Product Code
Most of the renowned telecom vendor is using this technique.
However, I was absolutely right about the identical Processor ID
issue. All three returned the same Processor ID when we put wmic cpu
get ProcessorId command in their command prompts.
Processor ID will be same if all the systems are running as virtual machines on the same hypervisor.
MAC ID seems fine. Only thing is users must be provided the option to reset the application, in case the MAC changes.
It looks like custom kitchen is the way for that.
SMBIOS UUID (motherboard serial) is not robust, but works fine in 99% cases. However some brands will set the same UUID for multiple computers (same production batch maybe). Getting it requires WMI access for the user (if he's not administrator), you can solve that by starting an external process asking administrator priviledges (check codeproject.com/Articles/15848/WMI-Namespace-Security)
Windows Product ID might be good, but I read it could be identical in some circumstances (https://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine)
Could someone clarify if the same Product ID (not product key) might be present on multiple computers ?
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid seems interesting. It's generated when installing Windows and if changed, it requires to reactivate Windows.
Mac Addresses are interresting but you can only take the first one or your unique ID will change when the interface is disabled, or when another network interface is added and appears first etc.
Hard Drive serial number is nice but when installing a ghost, it might also override the serial number from the original drive... And the HD serial is very easy to change.
The best might be to generate an ID with a combination of those machine identifiers and decide if the machine is the same by comparing those identifiers (ie if at least one Mac address + either SMBIOS UUID or Product ID is ok, accept)
How do I get the internal serial number of a USB-Stick or USB-HardDrive in C#?
Try this:
// add a reference to the System.Management assembly and
// import the System.Management namespace at the top in your "using" statement.
// Then in a method, or on a button click:
ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
foreach (ManagementObject currentObject in theSearcher.Get())
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}
Source: http://social.msdn.microsoft.com/forums/en-US/Vsexpressvcs/thread/f4447ed3-7e5f-4635-a28a-afff0b620156/
A solution using Win32 is described here
Edit: the original link seems to have gone missing. The above is a cached copy, and the author also wrote some sample code in VB.Net which is still online here.
I had problems with the solution offered by Yuval Adam as every USB stick I tried return blank on windows 7.
I solved this by just looking at the property PNPDeviceId on the current object.
E.g.
currentObject["PNPDeviceID"].ToString();
Not sure how valid this is but it worked for me on the 3 USB Sticks I tried