In part of a program I am writing, I'm trying to pull device information about specified local hard drives. I've been able to create a few value returning methods using the DriveInfo class like this:
//Gets drive format
public string GetDriveFormat(string driveName)
{
foreach (DriveInfo drive in DriveInfo.GetDrives())
{
if (drive.IsReady && drive.Name == driveName)
{
return drive.DriveFormat;
}
}
return "";
}
//Example of use
MessageBox.Show(GetDriveFormat("C:\\"));
The problem I'm running into now is that there doesn't seem to be a Model property to the DriveInfo class. I've looked all over but am unable to find a way to construct a value returning method that will return the model of a drive like what is viewable in device manager.
Any help would be greatly appreciated,
Thanks!
Unfortunately, you cannot get the Drive's Manufacturer and Model using the DriveInfo class.
You'll have to resort back to WMI:
WqlObjectQuery q = new WqlObjectQuery("SELECT * FROM Win32_DiskDrive");
using (ManagementObjectSearcher res = new ManagementObjectSearcher(q)) {
foreach (ManagementObject o in res.Get()) {
Console.WriteLine("Caption = " + o["Caption"]);
Console.WriteLine("DeviceID = " + o["DeviceID"]);
Console.WriteLine("Decsription = " + o["Description"]);
Console.WriteLine("Manufacturer = " + o["Manufacturer"]);
Console.WriteLine("MediaType = " + o["MediaType"]);
Console.WriteLine("Model = " + o["Model"]);
Console.WriteLine("Name = " + o["Name"]);
// only in Vista, 2008 & etc: //Console.WriteLine("SerialNumber = " + o["SerialNumber"]);
} }
Not sure if you need to consider mounted drives as well:
foreach(ManagementObject volume in new ManagementObjectSearcher("Select * from Win32_Volume" ).Get())
{
...
}
You'll need to use a lower-level API to get this information, and even then it still might not be accurate.* The internal details of the hard drives is exposed in the Win32 APIs, which you can still access in C# through WMI.
*: Note that this is still limited to the hardware information as Windows is able to see it. In some conditions, it won't or can't be accurate (e.g. with a RAID array, where Windows sees N drives as a single drive).
I'm not entirely sure if you can get that info without using lower level api's. This post should help you achieve your goal.
http://www.codeproject.com/Articles/17973/How-To-Get-Hardware-Information-CPU-ID-MainBoard-I
Quick summary of the link:
Add a reference to the System.Management library
Then you can use:
var disks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject disk in disks.Get())
{
Console.WriteLine(disk["Model"].ToString());
Console.WriteLine("\tSerial: " + disk["SerialNumber"]);
}
here is something that can also work for you feel free to tweak it as you please
String drive = "c";
ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + ":\"");
disk.Get();
Console.WriteLine(disk["VolumeName"]);
foreach (var props in disk.Properties)
{
Console.WriteLine(props.Name + " " + props.Value);
}
Console.ReadLine();
Related
I have been trying to find the amount of free storage space available in the fixed drive on a device in my UWP app. I have been using the following code to achieve this-
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
if (d.DriveType == DriveType.Fixed && d.IsReady)
{
double availableFreeSpaceInBytes = d.AvailableFreeSpace;
}
}
But whenever I run this, d.IsReady always returns false indicating that the device is not ready. I referred this- https://learn.microsoft.com/en-us/dotnet/api/system.io.driveinfo.isready?view=netframework-4.8. But haven't been able to understand.
Please help me with what am I doing wrong. Or is there any other way to achieve this?
If you only need to know the free space on the drive where your UWP app is installed (usually, the C: drive), you can use the following without adding any additional capabilities:
using Windows.Storage;
string freeSpaceKey = "System.FreeSpace";
var retrieveProperties = await ApplicationData.Current.LocalFolder.Properties.RetrievePropertiesAsync(new string[] { freeSpaceKey });
var freeSpaceRemaining = (ulong)retrieveProperties[freeSpaceKey];
Retrieving the amount of local storage on a device in UWP app
AvailableFreeSpace is not available in UWP system. For getting available free space, you need use StorageFolder System.FreeSpace property to achieve. Pleas note if you used GetFolderFromPathAsync metod, you need to allow broadFileSystemAccess capability before. Please refer this case link.
const String k_freeSpace = "System.FreeSpace";
const String k_totalSpace = "System.Capacity";
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
try
{
Debug.WriteLine("Drive: " + d.Name);
Debug.WriteLine("RootDir: " + d.RootDirectory.FullName);
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(d.RootDirectory.FullName);
var props = await folder.Properties.RetrievePropertiesAsync(new string[] { k_freeSpace, k_totalSpace });
Debug.WriteLine("FreeSpace: " + (UInt64)props[k_freeSpace]);
Debug.WriteLine("Capacity: " + (UInt64)props[k_totalSpace]);
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("Couldn't get info for drive {0}. Does it have media in it?", d.Name));
}
}
So i've used this code to get S.M.A.R.T. hard drive diagnostics info from Windows WMI:
http://vasters.com/archive/Reading-ATAPI-SMART-Data-From-Drives-Using-NET-Temperature-Anyone.html
It works on most computers and doesn't on others. After a little bit research and sample testing i found out that it doesn't work on computers whose Hard drives are connected with PCI Express instead of SATA.
var searcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData");
foreach (ManagementObject queryObj in searcher.Get())
{
//do stuff
}
This is where i get exception:
System.Management.ManagementException: 'Not supported'
Is there any other way to do this, or add something in this code to make it work?
I searched this code everywhere and couldn't find working for me, but finaly found on another forum so it's really simple in usage.
Just from my example another way to get WMI info. More Attributes of WMI Win32_DiskDrive you can find in Microsoft DOCs
https://github.com/Mityugin/greentest
string NamespacePath = "\\\\.\\ROOT\\cimv2";
string ClassName = "Win32_DiskDrive";
oClass = new ManagementClass(NamespacePath + ":" + ClassName);
foreach (ManagementObject oObject in oClass.GetInstances())
{
var sign = Convert.ToString(oObject["Signature"]);
var model = Convert.ToString(oObject["Model"]);
var status = Convert.ToString(oObject["Status"]);
if (Equals(sign,""))
{
TextBox1.AppendText("DISK model: " + model);
TextBox1.AppendText(Environment.NewLine);
TextBox1.AppendText("Status: " + status);
TextBox1.AppendText(Environment.NewLine);
if (!status.Equals("OK") || !model.Contains("SSD"))
{
//Here is info if Disk is not OK or model not SSD
}
}
}
This github solution is fine for detecting an SSD but will not tell you it is PCIE or NVMe. I have an SSD that is an older Samsung 960 series and it is an SSD connected via SATA.
The code you need to read an NVMe drive Temperature is on this website at How do I enumerate NVMe (M2) drives an get their temperature in c#?
Is there a way to show data of not initialised HDDs? I need an app to show if there are any not initialised disks. Trying that:
DriveInfo[] disks = DriveInfo.GetDrives();
foreach(DriveInfo d in disks)
{
Console.WriteLine(d.Name + " " + d.DriveFormat);
}
But it shows only already formatted partitions
I have tried this code, but it only retrieves the "ClassGuid". Is there a way to get the USB device's Interface Guid?
private void loadUsbDevices()
{
using (var searcher = new ManagementObjectSearcher(
#"SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE 'USB%'"))
{
ManagementObjectCollection collection = searcher.Get();
foreach (var device in collection)
{
Console.WriteLine(((string) device.GetPropertyValue("Name")) + " ("
+ ((string) device.GetPropertyValue("ClassGuid")) + ") "
+ ((string)device.GetPropertyValue("DeviceID")));
}
}
}
Since your device uses WinUSB as the driver, you have probably already arranged for a registry value named DeviceInterfaceGUIDs to be inserted in the registry for that device. You can retrieve that same value using SetupDiOpenDevRegKey and RegQueryValueExW. For some example code that does this, see this code from libusbp:
https://github.com/pololu/libusbp/blob/890379c54ef58de46afc60b9c3eccfe2bd66d523/src/windows/generic_interface_windows.c#L93
You can also find similar code in the source code of libusb.
Is it possible to read the sharing permissions assigned to a shared folder? I'm able to read in the local security settings programmaticaly (the ones found under Right Click > Properties > Security) no problem. But, I'm wondering how I can read the permissions under Right Click > Sharing and Security... > Permissions
Here is an image of the Permissions I want to read:
Is this possible? I'm running an XP Pro machine if it helps.
Edit:
As per my answer I was able to iterate through all the shares, and get the access you (ie the person running the program) has on that share, but have not found a way to read the permissions others have on that share. This was done using Win32_Share class, however it does not have an option for getting the share permissions of other users. If anyone has any helpful hints that would be a huge help.
I was able to get this working by expanding on the approach taken by Petey B. Also, be sure that the process that runs this code impersonates a privileged user on the server.
using System;
using System.Management;
...
private static void ShareSecurity(string ServerName)
{
ConnectionOptions myConnectionOptions = new ConnectionOptions();
myConnectionOptions.Impersonation = ImpersonationLevel.Impersonate;
myConnectionOptions.Authentication = AuthenticationLevel.Packet;
ManagementScope myManagementScope =
new ManagementScope(#"\\" + ServerName + #"\root\cimv2", myConnectionOptions);
myManagementScope.Connect();
if (!myManagementScope.IsConnected)
Console.WriteLine("could not connect");
else
{
ManagementObjectSearcher myObjectSearcher =
new ManagementObjectSearcher(myManagementScope.Path.ToString(), "SELECT * FROM Win32_LogicalShareSecuritySetting");
foreach(ManagementObject share in myObjectSearcher.Get())
{
Console.WriteLine(share["Name"] as string);
InvokeMethodOptions options = new InvokeMethodOptions();
ManagementBaseObject outParamsMthd = share.InvokeMethod("GetSecurityDescriptor", null, options);
ManagementBaseObject descriptor = outParamsMthd["Descriptor"] as ManagementBaseObject;
ManagementBaseObject[] dacl = descriptor["DACL"] as ManagementBaseObject[];
foreach (ManagementBaseObject ace in dacl)
{
try
{
ManagementBaseObject trustee = ace["Trustee"] as ManagementBaseObject;
Console.WriteLine(
trustee["Domain"] as string + #"\" + trustee["Name"] as string + ": " +
ace["AccessMask"] as string + " " + ace["AceType"] as string
);
}
catch (Exception error)
{
Console.WriteLine("Error: "+ error.ToString());
}
}
}
}
}
I know you can with Windows Home Server:
http://msdn.microsoft.com/en-us/library/bb425864.aspx
You can do this in MMC and most of that is available through code, so it should be possible. If you can't find it there then you should check out Windows API calls. I've seen it done in C++, so it should also be possible in C#. Sorry, I don't have any sample code or other links to provide for those. I'll see if I can dig some up though.
I also just saw this on SO:
how to create shared folder in C# with read only access?
Another good link:
http://social.msdn.microsoft.com/Forums/en/windowssdk/thread/de213b61-dc7e-4f33-acdb-893aa96837fa
The best I could come up with is iterating through all the shares on a machine and reading the permissions you have on the share.
ManagementClass manClass = new ManagementClass(#"\\" +computerName +#"\root\cimv2:Win32_Share"); //get shares
//run through all the shares
foreach (ManagementObject objShare in manClass.GetInstances())
{
//ignore system shares
if (!objShare.Properties["Name"].Value.ToString().Contains('$'))
{
//print out the share name and location
textBox2.Text += String.Format("Share Name: {0} Share Location: {1}", objShare.Properties["Name"].Value, objShare.Properties["Path"].Value) + "\n";
Int32 permissions = 0;
try
{
//get the access values you have
ManagementBaseObject result = objShare.InvokeMethod("GetAccessMask", null, null);
//value meanings: http://msdn.microsoft.com/en-us/library/aa390438(v=vs.85).aspx
permissions = Convert.ToInt32(result.Properties["ReturnValue"].Value);
}
catch (ManagementException me)
{
permissions = -1; //no permissions are set on the share
}
textBox2.Text += "You have permissions: " + permissions + "\n\n";
}
}
If anyone could figure out how to get the permissions others have on the share that would be amazing.