In Windows we have information about our Monitros - some unique name and id. e.g.
Acer xxx
Samsung xxx
I have qeuestion how to get the information in C#, because I know that serial number we can get from WMI:
root\WMI -> WmiMonitorID
and about displays:
root/CIMV2 Win32_DesktopMonitor
But I have to have this infromation together, it meens Aceer S/N xxx have id 1 in Windows
Have anybody some idea?
Give this a shot:
using System.Management;
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DesktopMonitor");
foreach (ManagementObject obj in searcher.Get())
Console.WriteLine("Description: {0}", obj ["Description"]);
EDIT:
And here's a link to a nice looking class that will retrieve the monitor details:
http://wmimonitor.svn.sourceforge.net/viewvc/wmimonitor/DisplayInfoWMIProvider/WMIProvider/WMIProvider.cs?view=markup
Here is the class associated with the above link. It should give you everything you need about the monitor:
//DisplayInfoWMIProvider (c) 2009 by Roger Zander
using System;
using System.Collections;
using System.Management.Instrumentation;
using System.DirectoryServices;
using System.Management;
//using System.Security.Principal;
using Microsoft.Win32;
using System.Text;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
[assembly: WmiConfiguration(#"root\cimv2", HostingModel = ManagementHostingModel.LocalSystem)]
namespace DisplayInfoWMIProvider
{
[System.ComponentModel.RunInstaller(true)]
public class MyInstall : DefaultManagementInstaller
{
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
System.Runtime.InteropServices.RegistrationServices RS = new System.Runtime.InteropServices.RegistrationServices();
//This should be fixed with .NET 3.5 SP1
//RS.RegisterAssembly(System.Reflection.Assembly.LoadFile(Environment.ExpandEnvironmentVariables(#"%PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\v3.5\System.Management.Instrumentation.dll")), System.Runtime.InteropServices.AssemblyRegistrationFlags.SetCodeBase);
}
public override void Uninstall(IDictionary savedState)
{
try
{
ManagementClass MC = new ManagementClass(#"root\cimv2:Win32_MonitorDetails");
MC.Delete();
}
catch { }
try
{
base.Uninstall(savedState);
}
catch { }
}
}
[ManagementEntity(Name = "Win32_MonitorDetails")]
public class DisplayDetails
{
[ManagementKey]
public string PnPID { get; set; }
[ManagementProbe]
public string SerialNumber { get; set; }
[ManagementProbe]
public string Model { get; set; }
[ManagementProbe]
public string MonitorID { get; set; }
/// <summary>
/// The Constructor to create a new instances of the DisplayDetails class...
/// </summary>
public DisplayDetails(string sPnPID, string sSerialNumber, string sModel, string sMonitorID)
{
PnPID = sPnPID;
SerialNumber = sSerialNumber;
Model = sModel;
MonitorID = sMonitorID;
}
/// <summary>
/// This Function returns all Monitor Details
/// </summary>
/// <returns></returns>
[ManagementEnumerator]
static public IEnumerable GetMonitorDetails()
{
//Open the Display Reg-Key
RegistryKey Display = Registry.LocalMachine;
Boolean bFailed = false;
try
{
Display = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Enum\DISPLAY");
}
catch
{
bFailed = true;
}
if (!bFailed & (Display != null))
{
//Get all MonitorIDss
foreach (string sMonitorID in Display.GetSubKeyNames())
{
RegistryKey MonitorID = Display.OpenSubKey(sMonitorID);
if (MonitorID != null)
{
//Get all Plug&Play ID's
foreach (string sPNPID in MonitorID.GetSubKeyNames())
{
RegistryKey PnPID = MonitorID.OpenSubKey(sPNPID);
if (PnPID != null)
{
string[] sSubkeys = PnPID.GetSubKeyNames();
//Check if Monitor is active
if (sSubkeys.Contains("Control"))
{
if (sSubkeys.Contains("Device Parameters"))
{
RegistryKey DevParam = PnPID.OpenSubKey("Device Parameters");
string sSerial = "";
string sModel = "";
//Define Search Keys
string sSerFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xff });
string sModFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xfc });
//Get the EDID code
byte[] bObj = DevParam.GetValue("EDID", null) as byte[];
if (bObj != null)
{
//Get the 4 Vesa descriptor blocks
string[] sDescriptor = new string[4];
sDescriptor[0] = Encoding.Default.GetString(bObj, 0x36, 18);
sDescriptor[1] = Encoding.Default.GetString(bObj, 0x48, 18);
sDescriptor[2] = Encoding.Default.GetString(bObj, 0x5A, 18);
sDescriptor[3] = Encoding.Default.GetString(bObj, 0x6C, 18);
//Search the Keys
foreach (string sDesc in sDescriptor)
{
if (sDesc.Contains(sSerFind))
{
sSerial = sDesc.Substring(4).Replace("\0", "").Trim();
}
if (sDesc.Contains(sModFind))
{
sModel = sDesc.Substring(4).Replace("\0", "").Trim();
}
}
}
if (!string.IsNullOrEmpty(sPNPID + sSerFind + sModel + sMonitorID))
{
yield return new DisplayDetails(sPNPID, sSerial, sModel, sMonitorID);
}
}
}
}
}
}
}
}
}
}
}
root/CIMV2/Win32_DesktopMonitor/PnPDeviceID
only show 2 of my 5 monitors
and root/WMI/WMIMonitorId/InstanceName
shows all 5 of my monitors
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\WMI")
Set colItems = objWMIService.ExecQuery( _
"SELECT * FROM WmiMonitorID",,48)
For Each objItem in colItems
Wscript.Echo "-----------------------------------"
Wscript.Echo "WmiMonitorID instance"
Wscript.Echo "-----------------------------------"
Wscript.Echo "InstanceName: " & objItem.InstanceName
Next
As an example, we use this to retrieve the serial from the primary HDD using WMI:
var search = new ManagementObjectSearcher("select * from Win32_LogicalDisk where DeviceID = 'C:'");
var serials = search.Get().OfType<ManagementObject>();
m_clientToken = serials.ElementAt(0)["VolumeSerialNumber"].ToString();
Perhaps you can utilize this to get your monitor information since you know which Mgmt Object to search. You basically use SQL to retrieve what you're looking for.
It seems to me that root/CIMV2/Win32_DesktopMonitor/PnPDeviceID (1) and root/WMI/WMIMonitorId/InstanceName (2) are nearly identical
I found the following on my computer using WMI Explorer
(1) DISPLAY\HWP2868\5&3EB7FBC&0&UID16777472
(2) DISPLAY\HWP2868\5&3eb7fbc&0&UID16777472_0
There are two differences: the _0 at the end of (2) and the fact that parts of (2) is lower case.
I do not have more than a single monitor for reference at the moment, therefore I can not provide you with a more accurate way to associate the two entries. But it looks to me like you could write two queries, modifying the search condition in one of them to match the other's format. But you need to investigate whether or not there is a reliable pattern to do so.
At any rate, there seems to be enough common elements to be able to make a match in code, if not by query.
Related
This question already has answers here:
SD card directory
(1 answer)
How to differentiate between USB device types?
(3 answers)
Closed 1 year ago.
How to get the drive letter of an SD Card connected to a PC, from a C# .NET Framework application?
I have looked at suggested questions on this topic, including this, this & this, but none of them give me the solution I need.
Using System.IO.DriveInfo.GetDrives() or System.Management.ManagementObjectSearcher() with query "Win32_LogicalDisk", I can get the drive letters of all devices, but I can't tell which device(s) is the SD card.
Using System.Management.ManagementObjectSearcher() with query "CIM_LogicalDevice", "Caption = 'SDHC Card'", I get 2 devices with the "SDHC Card" caption property, but no drive letters.
How can I get the drive letter of the SD Card or card reader?
Here is what I have tried so far:
using System;
using System.Management;
namespace Code3
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("\tfrom: 'ManagementObjectSearcher()' with query \"Win32_LogicalDisk\"");
var searcher1 = new ManagementObjectSearcher(#"\root\cimv2", "SELECT * FROM Win32_LogicalDisk");
foreach (ManagementBaseObject disk in searcher1.Get())
{
string diskID = disk.GetPropertyValue("DeviceID").ToString();
int driveType = Convert.ToInt32(disk.GetPropertyValue("DriveType"));
string diskCaption = disk.GetPropertyValue("Caption").ToString();
string diskDescription = disk.GetPropertyValue("Description").ToString();
string diskName = disk.GetPropertyValue("Name").ToString();
int diskMediaType = Convert.ToInt32(disk.GetPropertyValue("MediaType"));
Console.WriteLine($"{diskName} - ID: {diskID}, Caption: {diskCaption}, Desc.: {diskDescription,-16}, Drive Type: {driveType}, Media Type: {diskMediaType}.");
}
Console.WriteLine();
Console.WriteLine("\tfrom: 'ManagementObjectSearcher()' with query SelectQuery(\"CIM_LogicalDevice\", \"Caption = 'SDHC Card'\")");
ManagementScope mgmtScope = new ManagementScope(#"\root\cimv2");
SelectQuery devQuery = new SelectQuery("CIM_LogicalDevice", "Caption = 'SDHC Card'");
var searcher2 = new ManagementObjectSearcher(mgmtScope, devQuery);
foreach (ManagementBaseObject device in searcher2.Get())
{
Console.WriteLine($"{device.GetPropertyValue("Name"),-15} - Caption: {device.GetPropertyValue("Caption")}, Device ID: {device.GetPropertyValue("DeviceID")}.");
continue; // ... to skip property display
if (!string.IsNullOrEmpty(device.GetPropertyValue("Name").ToString()))
{
PropertyDataCollection props = device.Properties;
Console.WriteLine($"\n\t\tProperties of {device.GetPropertyValue("DeviceID")} Drive: \n");
foreach (var prop in device.Properties)
{
if (prop.Value != null)
Console.WriteLine($"{prop.Name,-20} - {prop.Type,-8} - {prop.Value ?? "(null)"}");
}
Console.WriteLine();
}
}
Console.ReadKey();
}
}
}
Thank you for any help you can give me.
EDIT:
From "CIM_LogicalDisk", I can see that "F:" drive is my SD-Card. (from 'VolumeName' property.)
From "CIM_LogicalDevice", I can see the "\.\PHYSICALDRIVE1" and "PCISTOR\DISK&VEN_RSPER&PROD_RTS5208LUN0&REV_1.00\0000" is my SD-Card. (from 'Name', 'Caption', and/or 'Model' properties.)
But my app can't see this! Note that 'drive letter' and 'PHYSICALDRIVE number' do not remain correlated, and can change as different removable devices are inserted and removed.
How can I get my code to make the connection between logical and physical drives?
If you are really sure that your SD card's volume label is always "SDHC Card" (which I am not), then you can use the following approach:
The DriveInfo class contains a static method GetDrives which returns an array of DriveInfo instances. Each instance itself represents on logical drive. You can use the VolumeLabel property to check the name of the volume.
So something like...
var drives = DriveInfo.GetDrives().Where(drive => drive.VolumeLabel == "SDHC Card");
...returns all drives where the volume is called "SDHC Card".
If you want to get the drive letter of the logical drive you can access it by using the RootDirectory property of a concrete instance.
Like:
var drives = DriveInfo.GetDrives().Where(drive => drive.VolumeLabel == "SDHC Card");
foreach (var drive in drives)
Console.WriteLine(drive.RootDirectory.FullName);
I finally got a solution worked out. Using WMI association classes, I was able to make the connection between logical and physical drives.
This class is my solution:
using System.Collections.Generic;
using System.Management;
namespace GetSDCard
{
public class GetSDCards
{
public Card[] GetCards()
{
return FindCards().ToArray();
}
private List<Card> FindCards()
{
List<Card> cards = new List<Card>();
// Get Disk Drives collection (Win32_DiskDrive)
string queryDD = "SELECT * FROM Win32_DiskDrive WHERE Caption = 'SDHC Card'";
using (ManagementObjectSearcher searchDD = new ManagementObjectSearcher(queryDD))
{
ManagementObjectCollection colDiskDrives = searchDD.Get();
foreach (ManagementBaseObject objDrive in colDiskDrives)
{
// Get associated Partitions collection (Win32_DiskDriveToDiskPartition)
string queryPart = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{objDrive["DeviceID"]}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
using (ManagementObjectSearcher searchPart = new ManagementObjectSearcher(queryPart))
{
ManagementObjectCollection colPartitions = searchPart.Get();
foreach (ManagementBaseObject objPartition in colPartitions)
{
// Get associated Logical Disk collection (Win32_LogicalDiskToPartition)
string queryLD = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{objPartition["DeviceID"]}'}} WHERE AssocClass = Win32_LogicalDiskToPartition";
using (ManagementObjectSearcher searchLD = new ManagementObjectSearcher(queryLD))
{
ManagementObjectCollection colLogicalDisks = searchLD.Get();
foreach (ManagementBaseObject objLogicalDisk in colLogicalDisks)
cards.Add(new Card($"{objLogicalDisk["DeviceID"]}", $"{objDrive["Caption"]}", $"{objLogicalDisk["VolumeName"]}"));
}
}
}
}
}
return cards;
}
public class Card
{
public string Drive { get; set; }
public string Name { get; set; }
public string Label { get; set; }
public Card(string _drive, string _name, string _label)
{
Drive = _drive;
Name = _name;
Label = _label;
}
}
}
}
Here is a simple console app to demonstrate how to use it.
using GetSDCard;
using System;
using System.IO;
namespace FindSDCard_Demo
{
class Program
{
static void Main(string[] args)
{
GetSDCards getter = new GetSDCards();
GetSDCards.Card[] sdCards = getter.GetCards();
if (sdCards.Length == 0)
Console.WriteLine("No SD Cards found.");
else
{
string sdDrive = sdCards[0].Drive;
Console.WriteLine($"Root folder of SD Card '{sdDrive}':");
foreach (var folder in Directory.GetDirectories(sdDrive))
Console.WriteLine($"\t{folder}");
}
}
}
}
I hope that this can save you the hours of frustration I went through.
Hello everyone I want to ask about how can list ports and mac addresses of devices connected to switch using C#.
I have found code which works for Dell switch. I need it for Cisco switch
using SnmpSharpNet;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PortMapper
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
List<KeyValuePair<string, string>> portList = new List<KeyValuePair<string, string>>();
List<Portmap> portMaps = new List<Portmap>();
public class Portmap
{
public string Hostname { get; set; }
public string Port { get; set; }
public string IP { get; set; }
public string MAC { get; set; }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IPAddress ip = IPAddress.Parse("192.168.0.2");
IPAddress ip2 = IPAddress.Parse("192.168.0.3");
SnmpWalk(ip, "community", "1.3.6.1.2.1.17.7.1.2.2.1.2.1", "1");
SnmpWalk(ip2, "community","1.3.6.1.2.1.17.7.1.2.2.1.2.1", "2");
DhcpQuery("netsh", "dhcp server \\\\servername scope 192.168.0.0 show clients", "192");
List<Portmap> gridResults = new List<Portmap>();
//Example of filtering uplink ports from other switches
foreach(Portmap portMap in portMaps)
{
if (portMap.Port != "1/2/48" && portMap.Port != "2/1/48")
{
gridResults.Add(portMap);
}
}
PortMapGrid.ItemsSource = gridResults;
}
//Use NETSH to retrieve a list of DHCP MAC and IP addresses
private void DhcpQuery(string cmd, string args, string subnet)
{
ProcessStartInfo procStartInfo = new ProcessStartInfo();
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.FileName = cmd;
procStartInfo.Arguments = args;
procStartInfo.CreateNoWindow = true;
string output;
using (Process proc = Process.Start(procStartInfo))
{
output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
}
//Find valid leases in command output
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
List<string> leases = new List<string>();
foreach (string line in lines)
{
if (line.StartsWith(subnet))
{
leases.Add(line);
}
}
//Create threads
Thread[] threadArray = new Thread[leases.Count];
int threadcount = 0;
//Loop each Dhcp Lease
foreach (string line in leases)
{
string[] pieces = line.Split('-');
string ipAddress = pieces[0].Trim();
string mac = "";
string hostname = "";
foreach (string piece in pieces)
{
if (piece.Trim().Length == 2)
{
mac += piece;
}
}
ThreadStart start = delegate
{
hostname = GetHost(ipAddress);
foreach (KeyValuePair<string, string> port in portList)
{
if (port.Key.ToUpper().Trim() == mac.ToUpper().Trim())
{
Portmap portMap = new Portmap();
portMap.IP = ipAddress;
portMap.MAC = mac.ToUpper();
portMap.Port = port.Value;
portMap.Hostname = hostname;
portMaps.Add(portMap);
}
}
};
threadArray[threadcount] = new Thread(start);
threadArray[threadcount].Start();
threadcount = threadcount + 1;
}
//Join all threads in the array to wait for results
for (int i = 0; i < threadcount; i++)
{
threadArray[i].Join();
}
}
//SNMPWALK the ports on a switch or stack of switches. Ports will be labeled SwitchNum/Stack Number/Port Numbers.
private void SnmpWalk(IPAddress ip, string snmpCommunity, string oid, string switchNum)
{
UdpTarget target = new UdpTarget(ip);
// SNMP community name
OctetString community = new OctetString(snmpCommunity);
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 1
param.Version = SnmpVersion.Ver1;
// Define Oid that is the root of the MIB tree you wish to retrieve
Oid rootOid = new Oid(oid);
// This Oid represents last Oid returned by the SNMP agent
Oid lastOid = (Oid)rootOid.Clone();
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.GetNext);
// Loop through results
while (lastOid != null)
{
// When Pdu class is first constructed, RequestId is set to a random value
// that needs to be incremented on subsequent requests made using the
// same instance of the Pdu class.
if (pdu.RequestId != 0)
{
pdu.RequestId += 1;
}
// Clear Oids from the Pdu class.
pdu.VbList.Clear();
// Initialize request PDU with the last retrieved Oid
pdu.VbList.Add(lastOid);
// Make SNMP request
SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
// You should catch exceptions in the Request if using in real application.
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);
lastOid = null;
break;
}
else
{
// Walk through returned variable bindings
foreach (Vb v in result.Pdu.VbList)
{
// Check that retrieved Oid is "child" of the root OID
if (rootOid.IsRootOf(v.Oid))
{
//Convert OID to MAC
string[] macs = v.Oid.ToString().Split('.');
string mac = "";
int counter = 0;
foreach (string chunk in macs)
{
if (counter >= macs.Length - 6)
{
mac += string.Format("{0:X2}", int.Parse(chunk));
}
counter += 1;
}
//Assumes a 48 port switch (52 actual). You need to know these values to correctly iterate through a stack of switches.
int dellSwitch = 1 + int.Parse(v.Value.ToString()) / 52;
int port = int.Parse(v.Value.ToString()) - (52 * (dellSwitch - 1));
KeyValuePair<string, string> Port = new KeyValuePair<string, string>(mac, switchNum + "/" + dellSwitch.ToString() + "/" + port.ToString());
portList.Add(Port);
//Exit Loop
lastOid = v.Oid;
}
else
{
//End of the requested MIB tree. Set lastOid to null and exit loop
lastOid = null;
}
}
}
}
else
{
Console.WriteLine("No response received from SNMP agent.");
}
}
target.Close();
}
private string GetHost(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
return entry.HostName;
}
catch
{
return "";
}
}
}
}
Can Anyone is going to help me out for finding the code or give me a way that how can I convert this code to work for Cisco. what Oid it can be?
Is there any possibility to determine how a c# application was being started?
In my case I want to check if this application (wpf) is being started by a shortcut located in a specific folder.
So, there are two ways to open my application
using direct shortcut
starting another application which is like an update manager to keep my application up to date. After checking, it starts my application with Process.Start()
And I want to ensure that the application is only able to be started with the update manager.
A trick you could use is to check the parent's PID, and then get some of the parent's process information.
If the parent's process name is something like "explorer.exe" then the application was started from the shortcut or directly by double-clicking it on explorer.
Otherwise, it was started from another application: it could be your updater application, it could also be another application with the same name as your updater application...
This means you have to re-think how deep you want to go for such a solution, and how deep do you want security control. You could pass arguments from your updater to your main application, or implement some inter-process communication with token exchanges... it is impossible to make a 100% secure system.
As someone commented above, this seems like a XY problem... or maybe not. Maybe it is just a security concern. It's recommended to revise what exactly are you aiming for this software.
In case you need sample code for retrieving process information in .NET (by using System.Management), then just give a try to the code listed below. All you have to do is to place it in a console application project named 'Updater', and correctly set the path to your main application in the code.
If you play a little bit with this example by starting and closing YourApplication.exe in different situations, then you should be able to see an output like this:
Parent process 'Updater.exe' [PID=5472]
Parent process 'explorer.exe' [PID=12052]
The code below was tested on VS2017 .Net 4.6.1
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
class Program
{
static void Main(string[] args)
{
Process.Start(new ProcessStartInfo()
{
FileName = "YourApplication.exe" // path to your application
});
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
Process process = Process.GetProcessesByName("YourApplication").FirstOrDefault(); // your application's process name
if (process == null)
{
Console.WriteLine($"Process is not running...");
continue;
}
ProcessManager pm = ProcessManager.FromLocalMachine();
var processProperties = pm.GetProcessProperties(process.Id);
int parentProcessId = Convert.ToInt32(processProperties[EProcessProperty.ParentProcessId]);
try
{
var parentProcessProperties = pm.GetProcessProperties(parentProcessId);
string parentProcessName = parentProcessProperties[EProcessProperty.Name].ToString();
Console.WriteLine($"Parent process '{parentProcessName ?? "Unknown"}' [PID={parentProcessId}]");
Console.WriteLine("---------------------------------");
}
catch { Console.WriteLine("Parent process information not found."); }
}
}
}
public class ProcessConnection
{
internal ManagementScope ManagementScope { get; }
internal ProcessConnection(string machineName, string user = null, string password = null, string domain = null)
{
ManagementScope = new ManagementScope
{
Path = new ManagementPath(#"\\" + machineName + #"\root\CIMV2"),
Options = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.Default,
EnablePrivileges = true,
Username = user == null ? null : (string.IsNullOrWhiteSpace(domain) ? user : $"{domain}\\{user}"),
Password = user == null ? null : password,
},
};
ManagementScope.Connect();
}
}
public class ProcessManager
{
public static ProcessManager FromLocalMachine() => new ProcessManager()
{
Machine = Environment.MachineName,
};
public static ProcessManager FromRemoteMachine(string machine, string user = null, string password = null, string domain = null) => new ProcessManager()
{
Machine = machine,
User = user,
Password = password,
Domain = domain,
};
private ProcessManager() { }
public string Machine { get; private set; }
public string User { get; private set; }
public string Password { get; private set; }
public string Domain { get; private set; }
private ProcessConnection Connection { get; set; }
private ManagementScope ManagementScope => Connection == null ? (Connection = new ProcessConnection(Machine, User, Password, Domain)).ManagementScope : Connection.ManagementScope;
public EProcessStartStatus StartProcess(string processPath)
{
ManagementClass mc = new ManagementClass($"\\\\{Machine}\\root\\CIMV2", "Win32_Process", null);
ManagementBaseObject process = mc.GetMethodParameters("Create");
process["CommandLine"] = processPath;
ManagementBaseObject createCode = mc.InvokeMethod("Create", process, null);
string createCodeStr = createCode["ReturnValue"].ToString();
return (EProcessStartStatus)Convert.ToInt32(createCodeStr);
}
public bool KillProcess(string processName)
{
try
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
foreach (ManagementObject mo in searcher.Get()) mo.InvokeMethod("Terminate", null);
return true;
}
catch { return false; }
}
public bool KillProcess(int processId)
{
try
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE ProcessId = '{processId}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
foreach (ManagementObject mo in searcher.Get()) mo.InvokeMethod("Terminate", null);
return true;
}
catch { return false; }
}
public void SetProcessPriority(string processName, EProcessPriority priority)
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(ManagementScope, query);
foreach (ManagementObject managementObject in managementObjectSearcher.Get())
{
ManagementBaseObject methodParams = managementObject.GetMethodParameters("SetPriority");
methodParams["Priority"] = priority;
managementObject.InvokeMethod("SetPriority", methodParams, null);
}
}
public string GetProcessOwner(string processName)
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
foreach (ManagementObject mo in searcher.Get())
{
ManagementBaseObject methodParams = mo.GetMethodParameters("GetOwner");
ManagementBaseObject owner = mo.InvokeMethod("GetOwner", null, null);
return owner["User"].ToString();
}
return null;
}
public string GetProcessOwnerSID(string processName)
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
foreach (ManagementObject mo in searcher.Get())
{
ManagementBaseObject methodParams = mo.GetMethodParameters("GetOwnerSid");
ManagementBaseObject OwnerSid = mo.InvokeMethod("GetOwnerSid", null, null);
return OwnerSid["Sid"].ToString();
}
return null;
}
public IList<int> GetRunningProcesses()
{
IList<int> processes = new List<int>();
SelectQuery query = new SelectQuery("SELECT * FROM Win32_Process");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
foreach (ManagementObject mo in searcher.Get()) processes.Add(int.Parse(mo["ProcessId"].ToString()));
return processes;
}
public IDictionary<EProcessProperty, object> GetProcessProperties(int processId)
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE ProcessId = '{processId}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
Dictionary<EProcessProperty, object> properties = new Dictionary<EProcessProperty, object>();
foreach (ManagementObject mo in searcher.Get())
{
foreach (PropertyData pd in mo.Properties)
{
if (Enum.TryParse(pd.Name, out EProcessProperty e)) properties[e] = pd.Value;
else Console.WriteLine(pd.Name + " is not mapped in the properties enumeration.");
}
}
return properties;
}
public IDictionary<EProcessProperty, object> GetProcessProperties(string processName)
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
Dictionary<EProcessProperty, object> properties = new Dictionary<EProcessProperty, object>();
foreach (ManagementObject mo in searcher.Get())
{
foreach (PropertyData pd in mo.Properties)
{
if (Enum.TryParse(pd.Name, out EProcessProperty e)) properties[e] = pd.Value;
else Console.WriteLine(pd.Name + " is not mapped in the properties enumeration.");
}
}
return properties;
}
public IList<int> GetProcessessFromExecutablePath(string executablePath)
{
SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE ExecutablePath = '{executablePath.Replace("\\", "\\\\")}'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
return searcher.Get().Cast<ManagementObject>().Select(mo => Convert.ToInt32(mo["ProcessId"])).ToList();
}
}
public enum EProcessPriority : uint
{
IDLE = 0x40,
BELOW_NORMAL = 0x4000,
NORMAL = 0x20,
ABOVE_NORMAL = 0x8000,
HIGH_PRIORITY = 0x80,
REALTIME = 0x100
}
public enum EProcessStartStatus
{
Success = 0,
AccessDenied = 2,
NoPermissions = 3,
Unknown = 8,
FileNotFound = 9,
Invalid = 21,
}
public enum EProcessProperty
{
Caption,
CommandLine,
CreationClassName,
CreationDate,
CSCreationClassName,
CSName,
Description,
ExecutablePath,
ExecutionState,
Handle,
HandleCount,
InstallDate,
KernelModeTime,
MaximumWorkingSetSize,
MinimumWorkingSetSize,
Name,
OSCreationClassName,
OSName,
OtherOperationCount,
OtherTransferCount,
PageFaults,
PageFileUsage,
ParentProcessId,
PeakPageFileUsage,
PeakVirtualSize,
PeakWorkingSetSize,
Priority,
PrivatePageCount,
ProcessId,
QuotaNonPagedPoolUsage,
QuotaPagedPoolUsage,
QuotaPeakNonPagedPoolUsage,
QuotaPeakPagedPoolUsage,
ReadOperationCount,
ReadTransferCount,
SessionId,
Status,
TerminationDate,
ThreadCount,
UserModeTime,
VirtualSize,
WindowsVersion,
WorkingSetSize,
WriteOperationCount,
WriteTransferCount,
}
If there are only 2 ways of starting your app, the second method should pass a parameter (a GUID?) to Process.Start() - generated by your updater app.
Maybe devise some kind of algorithm that allows the app to start only with the token.
From what I know this is impossible in the way you would like it to be but there's one trick which you can use. Firstly change your WPF application's entry method to get the command line arguments, and ( for example ) use -u argument to distinct from where the application was started. Then after -u you can pass a HWND or a process ID that matches your updater. Of course you have to then check if that application is running and if it's your updater.
example :
// updated process start
ProcessStartInfo psi = new ProcessStartInfo("your/WPF/application.exe");
psi.Arguments = "-u " + Process.GetCurrentProcess().Id;
// fill up rest of the properties you need
Process.Start(psi);
// wpf application's entry point
void Main(string[] args)
{
string updaterProcessIdstr = string.Empty;
for (int i = 0; i < args.Length; i++)
{
if(args[i] == "-u")
{
updaterProcessIdstr = args[i + 1];
i++;
}
}
int pid = int.Parse(updaterProcessIdstr);
Process updaterProcess = Process.GetProcessById(pid);
// do some validation here
// send something to stdin and read from stdout
// to determine if it was started from that updater.
}
As following i able to get usb com port names attached to 32bit win7OS machine, by given pid and vid,but when running in x64 it stuck in the following line:
comports.Add((string)rk6.GetValue("PortName"));
This is my code
static List<string> ComPortNames(String VID, String PID)
{
String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
List<string> comports = new List<string>();
RegistryKey rk1 = Registry.LocalMachine;
RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");
foreach (String s3 in rk2.GetSubKeyNames())
{
RegistryKey rk3 = rk2.OpenSubKey(s3);
foreach (String s in rk3.GetSubKeyNames())
{
if (_rx.Match(s).Success)
{
RegistryKey rk4 = rk3.OpenSubKey(s);
foreach (String s2 in rk4.GetSubKeyNames())
{
RegistryKey rk5 = rk4.OpenSubKey(s2);
RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
comports.Add((string)rk6.GetValue("PortName"));
}
}
}
}
return comports;
}
actual code get here, So how to get com port names in x64, any suggestion?
While I was testing the answer from Youkko under Windows 10 x64 I was getting some strange results and looking at the registry on my machine the LocationInformation keys contained strings such as Port_#0002.Hub_#0003so they are related to the USB hub / port the device is connected to not the COM port allocated by Windows.
So in my case I was getting COM2 included which is a hardware port on my motherboard and it skipped the COM5 port I was expecting but that was located under the PortName registry key. I'm not sure if something has changed since the version of Windows you were using but I think your main problem might have been not checking for null values on the keys.
The following slightly modified version seems to work fine on a variety or Windows 7 / 10 and x32 / 64 systems and I've also added a to check of SerialPort.GetPortNames() to make sure the device is available and plugged into the system before returning it:
static List<string> ComPortNames(String VID, String PID)
{
String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
List<string> comports = new List<string>();
RegistryKey rk1 = Registry.LocalMachine;
RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");
foreach (String s3 in rk2.GetSubKeyNames())
{
RegistryKey rk3 = rk2.OpenSubKey(s3);
foreach (String s in rk3.GetSubKeyNames())
{
if (_rx.Match(s).Success)
{
RegistryKey rk4 = rk3.OpenSubKey(s);
foreach (String s2 in rk4.GetSubKeyNames())
{
RegistryKey rk5 = rk4.OpenSubKey(s2);
string location = (string)rk5.GetValue("LocationInformation");
RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
string portName = (string)rk6.GetValue("PortName");
if (!String.IsNullOrEmpty(portName) && SerialPort.GetPortNames().Contains(portName))
comports.Add((string)rk6.GetValue("PortName"));
}
}
}
}
return comports;
}
By reading your code, I found out that the current path you're looking at in registry does not contain any information about ports.
But I found a way to read it by doing this little change:
static List<string> ComPortNames(String VID, String PID)
{
String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
List<string> comports = new List<string>();
RegistryKey rk1 = Registry.LocalMachine;
RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");
foreach (String s3 in rk2.GetSubKeyNames())
{
RegistryKey rk3 = rk2.OpenSubKey(s3);
foreach (String s in rk3.GetSubKeyNames())
{
if (_rx.Match(s).Success)
{
RegistryKey rk4 = rk3.OpenSubKey(s);
foreach (String s2 in rk4.GetSubKeyNames())
{
RegistryKey rk5 = rk4.OpenSubKey(s2);
string location = (string)rk5.GetValue("LocationInformation");
if (!String.IsNullOrEmpty(location))
{
string port = location.Substring(location.IndexOf('#') + 1, 4).TrimStart('0');
if (!String.IsNullOrEmpty(port)) comports.Add(String.Format("COM{0:####}", port));
}
//RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
//comports.Add((string)rk6.GetValue("PortName"));
}
}
}
}
return comports;
}
It did work perfectly.
Thank you for your code, by the way... It helped me a lot!
Here is my take on this (even if it is not a direct A to the Q)
USB devices is always (and has always) enumerated under HKLM\SYSTEM\CurrentControlSet\Enum\USB (note USB at the end)
Device nodes have the format VID_xxxx&PID_xxxx* where xxxx is hexadecimal, there might be some extra function data at the end
Each device node has a sub identifier node based on serialnumber or other data of the device and functions
identifier node can have value "FriendlyName" which some times have the COM in parantheses such as "Virtual Serial Port (COM6)"
Resulting path: HKLM\SYSTEM\CurrentControlSet\Enum\USB\VID_xxxx&PID_xxxx*\*\Device Parameters\ has value named "PortName"
Currently available com ports is listed by System.IO.Ports.SerialPort.GetPortNames()
OpenSubKey implements IDisposable and should have using or .Dispose() on them
using System.IO.Ports;
using System.Linq;
using Microsoft.Win32;
public class UsbSerialPort
{
public readonly string PortName;
public readonly string DeviceId;
public readonly string FriendlyName;
private UsbSerialPort(string name, string id, string friendly)
{
PortName = name;
DeviceId = id;
FriendlyName = friendly;
}
private static IEnumerable<RegistryKey> GetSubKeys(RegistryKey key)
{
foreach (string keyName in key.GetSubKeyNames())
using (var subKey = key.OpenSubKey(keyName))
yield return subKey;
}
private static string GetName(RegistryKey key)
{
string name = key.Name;
int idx;
return (idx = name.LastIndexOf('\\')) == -1 ?
name : name.Substring(idx + 1);
}
public static IEnumerable<UsbSerialPort> GetPorts()
{
var existingPorts = SerialPort.GetPortNames();
using (var enumUsbKey = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Enum\USB"))
{
if (enumUsbKey == null)
throw new ArgumentNullException("USB", "No enumerable USB devices found in registry");
foreach (var devBaseKey in GetSubKeys(enumUsbKey))
{
foreach (var devFnKey in GetSubKeys(devBaseKey))
{
string friendlyName =
(string) devFnKey.GetValue("FriendlyName") ??
(string) devFnKey.GetValue("DeviceDesc");
using (var devParamsKey = devFnKey.OpenSubKey("Device Parameters"))
{
string portName = (string) devParamsKey?.GetValue("PortName");
if (!string.IsNullOrEmpty(portName) &&
existingPorts.Contains(portName))
yield return new UsbSerialPort(portName, GetName(devBaseKey) + #"\" + GetName(devFnKey), friendlyName);
}
}
}
}
}
public override string ToString()
{
return string.Format("{0} Friendly: {1} DeviceId: {2}", PortName, FriendlyName, DeviceId);
}
}
Ok, using ManagementObjectSearcher (it gives COM-port index and VID and PID if they exist):
List < List <string>> USBCOMlist = new List<List<string>>();
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_PnPEntity");
foreach (ManagementObject queryObj in searcher.Get())
{
if (queryObj["Caption"].ToString().Contains("(COM"))
{
List<string> DevInfo = new List<string>();
string Caption = queryObj["Caption"].ToString();
int CaptionIndex = Caption.IndexOf("(COM");
string CaptionInfo = Caption.Substring(CaptionIndex + 1).TrimEnd(')'); // make the trimming more correct
DevInfo.Add(CaptionInfo);
string deviceId = queryObj["deviceid"].ToString(); //"DeviceID"
int vidIndex = deviceId.IndexOf("VID_");
int pidIndex = deviceId.IndexOf("PID_");
string vid = "", pid = "";
if (vidIndex != -1 && pidIndex != -1)
{
string startingAtVid = deviceId.Substring(vidIndex + 4); // + 4 to remove "VID_"
vid = startingAtVid.Substring(0, 4); // vid is four characters long
//Console.WriteLine("VID: " + vid);
string startingAtPid = deviceId.Substring(pidIndex + 4); // + 4 to remove "PID_"
pid = startingAtPid.Substring(0, 4); // pid is four characters long
}
DevInfo.Add(vid);
DevInfo.Add(pid);
USBCOMlist.Add(DevInfo);
}
}
}
catch (ManagementException e)
{
MessageBox.Show(e.Message);
}
I think ManagementObjectSearcher may be a better approach than directly reading the registry.
Here's an example for virtual COM ports.
I need in my program to tie a license to a hardware ID. I tried use WMI, but it still slow.
I need, for example, CPU, HDD, and motherboard info.
For more details refer to this link
The following code will give you CPU ID:
namespace required System.Management
var mbs = new ManagementObjectSearcher("Select ProcessorId From Win32_processor");
ManagementObjectCollection mbsList = mbs.Get();
string id = "";
foreach (ManagementObject mo in mbsList)
{
id = mo["ProcessorId"].ToString();
break;
}
For Hard disk ID and motherboard id details refer this-link
To speed up this procedure, make sure you don't use SELECT *, but only select what you really need. Use SELECT * only during development when you try to find out what you need to use, because then the query will take much longer to complete.
I got here looking for the same thing and I found another solution. If you guys are interested I share this class:
using System;
using System.Management;
using System.Security.Cryptography;
using System.Security;
using System.Collections;
using System.Text;
namespace Security
{
/// <summary>
/// Generates a 16 byte Unique Identification code of a computer
/// Example: 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9
/// </summary>
public class FingerPrint
{
private static string fingerPrint = string.Empty;
public static string Value()
{
if (string.IsNullOrEmpty(fingerPrint))
{
fingerPrint = GetHash("CPU >> " + cpuId() + "\nBIOS >> " +
biosId() + "\nBASE >> " + baseId() +
//"\nDISK >> "+ diskId() + "\nVIDEO >> " +
videoId() +"\nMAC >> "+ macId()
);
}
return fingerPrint;
}
private static string GetHash(string s)
{
MD5 sec = new MD5CryptoServiceProvider();
ASCIIEncoding enc = new ASCIIEncoding();
byte[] bt = enc.GetBytes(s);
return GetHexString(sec.ComputeHash(bt));
}
private static string GetHexString(byte[] bt)
{
string s = string.Empty;
for (int i = 0; i < bt.Length; i++)
{
byte b = bt[i];
int n, n1, n2;
n = (int)b;
n1 = n & 15;
n2 = (n >> 4) & 15;
if (n2 > 9)
s += ((char)(n2 - 10 + (int)'A')).ToString();
else
s += n2.ToString();
if (n1 > 9)
s += ((char)(n1 - 10 + (int)'A')).ToString();
else
s += n1.ToString();
if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-";
}
return s;
}
#region Original Device ID Getting Code
//Return a hardware identifier
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;
}
private static string cpuId()
{
//Uses first CPU identifier available in order of preference
//Don't get all identifiers, as it is very time consuming
string retVal = identifier("Win32_Processor", "UniqueId");
if (retVal == "") //If no UniqueID, use ProcessorID
{
retVal = identifier("Win32_Processor", "ProcessorId");
if (retVal == "") //If no ProcessorId, use Name
{
retVal = identifier("Win32_Processor", "Name");
if (retVal == "") //If no Name, use Manufacturer
{
retVal = identifier("Win32_Processor", "Manufacturer");
}
//Add clock speed for extra security
retVal += identifier("Win32_Processor", "MaxClockSpeed");
}
}
return retVal;
}
//BIOS Identifier
private static string biosId()
{
return identifier("Win32_BIOS", "Manufacturer")
+ identifier("Win32_BIOS", "SMBIOSBIOSVersion")
+ identifier("Win32_BIOS", "IdentificationCode")
+ identifier("Win32_BIOS", "SerialNumber")
+ identifier("Win32_BIOS", "ReleaseDate")
+ identifier("Win32_BIOS", "Version");
}
//Main physical hard drive ID
private static string diskId()
{
return identifier("Win32_DiskDrive", "Model")
+ identifier("Win32_DiskDrive", "Manufacturer")
+ identifier("Win32_DiskDrive", "Signature")
+ identifier("Win32_DiskDrive", "TotalHeads");
}
//Motherboard ID
private static string baseId()
{
return identifier("Win32_BaseBoard", "Model")
+ identifier("Win32_BaseBoard", "Manufacturer")
+ identifier("Win32_BaseBoard", "Name")
+ identifier("Win32_BaseBoard", "SerialNumber");
}
//Primary video controller ID
private static string videoId()
{
return identifier("Win32_VideoController", "DriverVersion")
+ identifier("Win32_VideoController", "Name");
}
//First enabled network card ID
private static string macId()
{
return identifier("Win32_NetworkAdapterConfiguration",
"MACAddress", "IPEnabled");
}
#endregion
}
}
I won't take any credit for this because I found it here
It worked faster than I expected for me. Without the graphic card, mac and drive id's I got the unique ID in about 2-3 seconds. With those above included I got it in about 4-5 seconds.
Note: Add reference to System.Management.
The following approach was inspired by this answer to a related (more general) question.
The approach is to read the MachineGuid value in registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography. This value is generated during OS installation.
There are few ways around the uniqueness of the Hardware-ID per machine using this approach. One method is editing the registry value, but this would cause complications on the user's machine afterwards. Another method is to clone a drive image which would copy the MachineGuid value.
However, no approach is hack-proof and this will certainly be good enough for normal users. On the plus side, this approach is quick performance-wise and simple to implement.
public string GetMachineGuid()
{
string location = #"SOFTWARE\Microsoft\Cryptography";
string name = "MachineGuid";
using (RegistryKey localMachineX64View =
RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
using (RegistryKey rk = localMachineX64View.OpenSubKey(location))
{
if (rk == null)
throw new KeyNotFoundException(
string.Format("Key Not Found: {0}", location));
object machineGuid = rk.GetValue(name);
if (machineGuid == null)
throw new IndexOutOfRangeException(
string.Format("Index Not Found: {0}", name));
return machineGuid.ToString();
}
}
}
We use a combination of the processor id number (ProcessorID) from Win32_processor and the universally unique identifier (UUID) from Win32_ComputerSystemProduct:
ManagementObjectCollection mbsList = null;
ManagementObjectSearcher mos = new ManagementObjectSearcher("Select ProcessorID From Win32_processor");
mbsList = mos.Get();
string processorId = string.Empty;
foreach (ManagementBaseObject mo in mbsList)
{
processorId = mo["ProcessorID"] as string;
}
mos = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct");
mbsList = mos.Get();
string systemId = string.Empty;
foreach (ManagementBaseObject mo in mbsList)
{
systemId = mo["UUID"] as string;
}
var compIdStr = $"{processorId}{systemId}";
Previously, we used a combination: processor ID ("Select ProcessorID From Win32_processor") and the motherboard serial number ("SELECT SerialNumber FROM Win32_BaseBoard"), but then we found out that the serial number of the motherboard may not be filled in, or it may be filled in with uniform values:
To be filled by O.E.M.
None
Default string
Therefore, it is worth considering this situation.
Also keep in mind that the ProcessorID number may be the same on different computers.
I have refactored Alex Sutu approach to be faster and simpler code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.Security.Cryptography;
namespace Test
{
/// <summary>
/// Generates a Guid based on the current computer hardware
/// Example: C384B159-8E36-6C85-8ED8-6897486500FF
/// </summary>
public class SystemGuid
{
private static string _systemGuid = string.Empty;
public static string Value()
{
if (string.IsNullOrEmpty(_systemGuid))
{
var lCpuId = GetCpuId();
var lBiodId = GetBiosId();
var lMainboard = GetMainboardId();
var lGpuId = GetGpuId();
var lMac = GetMac();
var lConcatStr = $"CPU: {lCpuId}\nBIOS:{lBiodId}\nMainboard: {lMainboard}\nGPU: {lGpuId}\nMAC: {lMac}";
_systemGuid = GetHash(lConcatStr);
}
return _systemGuid;
}
private static string GetHash(string s)
{
try
{
var lProvider = new MD5CryptoServiceProvider();
var lUtf8 = lProvider.ComputeHash(ASCIIEncoding.UTF8.GetBytes(s));
return new Guid(lUtf8).ToString().ToUpper();
}
catch (Exception lEx)
{
return lEx.Message;
}
}
#region Original Device ID Getting Code
//Return a hardware identifier
private static string GetIdentifier(string pWmiClass, List<string> pProperties)
{
string lResult = string.Empty;
try
{
foreach (ManagementObject lItem in new ManagementClass(pWmiClass).GetInstances())
{
foreach (var lProperty in pProperties)
{
try
{
switch(lProperty)
{
case "MACAddress":
if (string.IsNullOrWhiteSpace(lResult) == false)
return lResult; //Return just the first MAC
if (lItem["IPEnabled"].ToString() != "True")
continue;
break;
}
var lItemProperty = lItem[lProperty];
if (lItemProperty == null)
continue;
var lValue = lItemProperty.ToString();
if (string.IsNullOrWhiteSpace(lValue) == false)
lResult += $"{lValue}; ";
}
catch { }
}
}
}
catch{}
return lResult.TrimEnd(' ', ';');
}
private static List<string> ListOfCpuProperties = new List<string>{ "UniqueId", "ProcessorId", "Name", "Manufacturer" };
private static string GetCpuId()
{
return GetIdentifier("Win32_Processor", ListOfCpuProperties);
}
private static List<string> ListOfBiosProperties = new List<string> { "Manufacturer", "SMBIOSBIOSVersion", "IdentificationCode", "SerialNumber", "ReleaseDate", "Version" };
//BIOS Identifier
private static string GetBiosId()
{
return GetIdentifier("Win32_BIOS", ListOfBiosProperties);
}
private static List<string> ListOfMainboardProperties = new List<string> { "Model", "Manufacturer", "Name", "SerialNumber" };
//Motherboard ID
private static string GetMainboardId()
{
return GetIdentifier("Win32_BaseBoard", ListOfMainboardProperties);
}
private static List<string> ListOfGpuProperties = new List<string> { "Name" };
//Primary video controller ID
private static string GetGpuId()
{
return GetIdentifier("Win32_VideoController", ListOfGpuProperties);
}
private static List<string> ListOfNetworkProperties = new List<string> { "MACAddress" };
private static string GetMac()
{
return GetIdentifier("Win32_NetworkAdapterConfiguration", ListOfNetworkProperties);
}
#endregion
}
}
Here is a DLL that shows:
* Hard drive ID (unique hardware serial number written in drive's IDE electronic chip)
* Partition ID (volume serial number)
* CPU ID (unique hardware ID)
* CPU vendor
* CPU running speed
* CPU theoretic speed
* Memory Load ( Total memory used in percentage (%) )
* Total Physical ( Total physical memory in bytes )
* Avail Physical ( Physical memory left in bytes )
* Total PageFile ( Total page file in bytes )
* Available PageFile( Page file left in bytes )
* Total Virtual( Total virtual memory in bytes )
* Available Virtual ( Virtual memory left in bytes )
* Bios unique identification numberBiosDate
* Bios unique identification numberBiosVersion
* Bios unique identification numberBiosProductID
* Bios unique identification numberBiosVideo
(text grabbed from original web site)
It works with C#.