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
Related
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());
}
}
}
since some time now I try to figure out how to correctly setup this new UWF (Unified Write Filter). Unfortunately it seems there is only documentation for Win 8.1 industry (here), not for Win 10. I hope there were no relevant changes since.
I also asked this on the WindowsDevCenter but got no response so far.
Here is my problem:
With the WMI providers I got UWF enabled by now (UWF_Filter.Enable()), but I cannot protect any volume.
Also the volume list looks very strange: There are 4 entrys, everyone is with CurrentSession=True.
The first is for an volume with no drive letter, only a volume id.
The second is for C:
and then there are 2 identical for D: .
Should'nt there normally be 2 entrys per volume, one where CurrentSession is true and one where its false, meaning its the setting applied after reboot?
If I try to execute Protect on the ManagementObject with DriveLetter=C: I get an Access denied exception, I assume because its the object for the current session.
Also if I try uwfmgr.exe Volume Protect C: on the console it simply hangs: no reaction, no error, only a forever blinking cursor. EDIT: it turned out this was a problem caused by another installed software. See also below.
Do I have to enable or disable or do anything else before I can protect volumes?
Thanks in advance,
Sebastian
My system:
Windows 10 IOT Enterprise 2016 LTSB x64
1 SSD 250GB with Boot, C: and D:
Edit:
Here I asked a follow up question with some other details and a workaround. If I use uwfmgr.exe volume protect c: for example, it works and UWF_Volume now suddenly has (the correct) 2 entries for C:, one for the current and one for the next session.
However I want to avoid this, because IMHO it should be solveable by WMI only.
Edit 2: #sommmen
The partition layout is as following: One disk with 4 partitions.
Boot, 500MB
C:/ , 45GB
unknown, 500MB (Boot-Backup I think)
D:/ , ~200GB
PS:
Please could anyone create the tags uwf and uwfmgr? Would be nice :-)
Missing UWF_Volume instances often appeared after reboot in my tests. But if not, you can create them directly using ManagementClass.CreateInstance().
The problem here is that the official docs are not exactly correct. The description of the UWF_Volume.VolumeName property is:
The unique identifier of the volume on the current system. The
VolumeName is the same as the DeviceID property of the Win32_Volume
class for the volume.
from: https://learn.microsoft.com/en-us/windows-hardware/customize/enterprise/uwf-volume#properties
In fact, the DeviceID needs a slight modification, before using it as value for UWF_Volume.VolumeName:
DeviceID.Substring(4).TrimEnd('\\')
So, after removing prefix \\?\ and removing any trailing slashes you can create instances with CurrentSession=false for the specified device.
This also works in Windows 10 Pro without any uwfmgr.exe. Though, officially not recommended/supported.
Also, I was not able to delete instances, yet. So be sure to add only correct values.
Full Example:
// example value
var DeviceId_From_Win32_Volume = #"\\?\Volume{c2eac053-27e3-4f94-b28c-c2c53d5f4fe1}\";
// example value
var myDriveLetter = "C:";
var myDeviceId = DeviceId_From_Win32_Volume.Substring(4).TrimEnd('\\');
var wmiNamespace = "root\\standardcimv2\\embedded";
var className = "UWF_Volume";
var mgmtScope = new ManagementScope {Path = {NamespacePath = wmiNamespace}};
var mgmtPath = new ManagementPath(className);
var mgmtClass = new ManagementClass(mgmtScope, mgmtPath, null);
// prepare the new object
var newObj = mgmtClass.CreateInstance();
newObj.SetPropertyValue("DriveLetter", myDriveLetter);
newObj.SetPropertyValue("VolumeName", myDeviceId);
newObj.SetPropertyValue("CurrentSession", false);
newObj.SetPropertyValue("CommitPending", false);
newObj.SetPropertyValue("BindByDriveLetter", false);
// create the WMI instance
newObj.Put(new PutOptions {Type = PutType.CreateOnly});
I experience the similar issue in that I could not query the UWF_Volume with CurrentSession=False. However, there's one thing I did that seems to "generate" the UWF_Volume management object with CurrentSession=False. I ran "uwfmgr volume protect c:". Unfortunately, in your case running this causes it to hang.
Could you try running uwfmgr in cmd in admin? Also, if you run "uwfmgr get-config", would you be able to get the current setting of the write filter?
Another thing from your description: you said there are two identical volumes for D:, but if you looks closely at the properties, one would be CurrentSession=True, and the other one is CurrentSession=False. According to the documentation, if you want to make change, you must select the management object (UWF_Volume) with CurrentSession=False.
https://learn.microsoft.com/en-us/windows-hardware/customize/enterprise/uwf-volume
(scroll down to powershell script code sample section)
First of all a volume may have several partitions. They will show up as having the same drive label.
e.g.
C:/ //?/{some guid here}
C:/ //?/{some other guid here}
Now this is common for the %systemDrive% because this has the boot partition.
You can use the commands
mountvol
and
Diskpart
List volume
To figure out the right guid for your need (or you can protect both the boot partition and the system partition). Also using wmi you can look at Win32_volume under namespace cimv2 to get some more insight.
The command line util UWFmgr seems to create an UWF_VOLUME wmi instance once you run the protect command. The docs also hint that you need to create an object yourself.
function Set-ProtectVolume($driveLetter, [bool] $enabled) {
# Each volume has two entries in UWF_Volume, one for the current session and one for the next session after a restart
# You can only change the protection status of a drive for the next session
$nextConfig = Get-WMIObject -class UWF_Volume #CommonParams |
where {
$_.DriveLetter -eq "$driveLetter" -and $_.CurrentSession -eq $false
};
# If a volume entry is found for the drive letter, enable or disable protection based on the $enabled parameter
if ($nextConfig) {
Write-Host "Setting drive protection on $driveLetter to $enabled"
if ($Enabled -eq $true) {
$nextConfig.Protect() | Out-Null;
} else {
$nextConfig.Unprotect() | Out-Null;
}
}
=======> (!) im talking about this comment
# If the drive letter does not match a volume, create a new UWF_volume instance
else {
Write-Host "Error: Could not find $driveLetter. Protection is not enabled."
}
}
The docs however do not provide a method of doing this. For now it seems we need to use the command line util till someone has an example using the WMI provider.
To answer my own question: So far I have only a workaround but no real solution.
It is to check if there is an entry with CurrentSession=False and if not invoke the command directly:
ManagementObjectSearcher ms = new ManagementObjectSearcher(_Scope, new ObjectQuery("select * from UWF_Volume where VolumeName = \"" + volId + "\" AND CurrentSession=\"False\""));
ManagementObjectCollection c = ms.Get();
UInt32 res = 1;
foreach (ManagementObject mo in c)
{
// entry found: do it with WMI
res = (UInt32)mo.InvokeMethod(newState ? "Protect" : "Unprotect", new object[] { });
}
if (c.Count == 1 && res == 0)
// message: success
if (c.Count == 0)
{
// no entry found: invoke cmd
ProcessStartInfo info = new ProcessStartInfo("uwfmgr.exe", "volume " + (newState ? "Protect" : "Unprotect") + #" \\?\" + volId);
Process process = new Process();
info.Verb = "runas"; //needs admin
process.StartInfo = info;
process.Start();
process.WaitForExit();
}
This has the side effect that for a split second a command line window will pop up, but nevertheless it works well.
I searched a lot but did not find any working codes getting SPD tables information via C#. Out there there are lots of softwares which get this info but HOW?
as shown in the image, for RAM devices, you can see Manufacture's name which can not be retrieve at all by WMI etc
If there is a DLL for using in C# will be perfect also
After some Research found this:
https://github.com/sapozhnikovay/SMBIOS
but it can not read table 17 to get memory device information.
Once I was researching about this, you need to get this information through SMBUS (not SMBIOS). But you need to create a driver (WDM in C/C++) to access this information.
Make sure you have added System.Management as a reference.
Here is a string that will return almost any information you want from the component :
private string getComponent(string hwClass, string syntax)
{
ManagementObjectSearcher mos = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hwClass);
foreach (ManagementObject mj in mos.Get())
{
return Convert.ToString(mj[syntax]);
}
return null;
}
Using the string would look like this, say on a button click :
label1.Text = getComponent("Win32_PhysicalMemory", "SerialNumber");
I tested it and it returned a serial number, you can also look at the list of things you can put in like manufacturer, name, capacity etc.
I got all of this information from this YouTube video.
You can find all of the devices and their properties here (CPU, GPU, etc.)
I need to get basic information about the computer's processor in a WPF application I'm writing.
Data such as "Intel(R) core(TM) 2 Quad CPU Q6600 # 2.4GHz"
How do I do this?
Use WMI
using System.Management;
private static string GetProcessorID()
{
ManagementClass mgt = new ManagementClass("Win32_Processor");
ManagementObjectCollection procs= mgt.GetInstances();
foreach ( ManagementObject item in procs)
return item.Properties["Name"].Value.ToString();
return "Unknown";
}
This information (and much, much more) is available via Windows Management Instrumentation (or WMI for short). It isn't technically tied to WPF. Please take a look at this article to get you started!
Some of what you're looking for is exposed by properties of the System.Environment class. You might also be interested in the System.Windows.Forms.SystemInformation class.
Use WMI to obtain the information needed, especially the classes in the System.Management namespace. First. add a reference to the System.Management assembly, then use code similar to this one:
ManagementClass wmiManagementProcessorClass = new ManagementClass("Win32_Processor");
ManagementObjectCollection wmiProcessorCollection = wmiManagementProcessorClass.GetInstances();
foreach (ManagementObject wmiProcessorObject in wmiProcessorCollection)
{
try
{
MessageBox.Show(wmiProcessorObject.Properties["Name"].Value.ToString());
}
catch (ManagementException ex)
{
// real error handling here
MessageBox.Show(ex.Message);
}
}
Hi i'v look through the WMI class... but none can help me in getting the partition table information... now i'm having a project which is to display the USB thumbdrive's .MBR how should i go about it? really puzzle... Any help and guide will be very much appreciated!
p.s. the code can only be written in C#
Edit
Thank you! I've browse through the CreateFile documentation... Still wondering how should I use P/Invoke to call CreateFile and to read the boot sector( display out the .MBR )? Do you have any reference code for this portion? Thank you once again!!
If you want you can use WMI to get information about any drive. To do this you need to query the corresponding WMI classes. With C# you must add these references:
System.Management
and using statements:
using System.Management;
To get disk info for which are attached to your computer you can use this query:
Select * From Win32_DiskDrive
with C#, you can query like:
SelectQuery wmi_sorgusu = new SelectQuery("Select * from Win32_DiskDrive");
ManagementObjectSearcher wmi_bulucu = new ManagementObjectSearcher( wmi_sorgusu );
foreach (ManagementObject wmi_nesne in wmi_bulucu.Get()) {
Console.WriteLine(wmi_nesne.GetPropertyValue( "DeviceID" ).ToString());
Console.WriteLine(wmi_nesne.GetPropertyValue( "InterfaceType" ).ToString());
Console.WriteLine(wmi_nesne.GetPropertyValue( "Caption" ).ToString());
Console.WriteLine(wmi_nesne.GetPropertyValue( "Status" ).ToString());
Console.WriteLine(wmi_nesne.GetPropertyValue( "MediaLoaded" ).ToString());
//... etc
}
After getting the device parameters, you can use the same method to query Win32_DiskPartition WMI Class. You can give the device parameters to SELECT query as WHERE clause. Queries to Win32_DiskPartition returns all the partitions of all drives attached to system.
If you're prepared to parse the raw information yourself, you can use P/Invoke to call CreateFile. If your user account has enough mojo, you can open the raw disk device by passing it a string, something like "\\.\PHYSICALDRIVE0". See the documentation for CreateFile for more details.
To be honest, I would be very much surprised if you can't open it with IO.FileStream with the same magic path.
Indeed C# FileStream cannot open physical device directly:
Unhandled Exception: System.ArgumentException: FileStream will not
open Win32 devices such as disk partitions and tape drives. Avoid use
of "\.\" in the path.