Jak dobrać się do danych o dysku SSD z poziomu c#?
Napisałem taki kod:
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Management;
using System.ComponentModel;
public class SmartInfo
{
public void GetDiskUsageTime(out TimeSpan readTime, out TimeSpan writeTime)
{
try
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PerfFormattedData_PerfDisk_PhysicalDisk");
foreach (ManagementObject disk in searcher.Get())
{
var diskName = disk["Name"].ToString().Trim();
if (diskName.StartsWith("PhysicalDisk"))
{
readTime = TimeSpan.FromMilliseconds(Convert.ToUInt32(disk["AvgDiskReadTime"]));
writeTime = TimeSpan.FromMilliseconds(Convert.ToUInt32(disk["AvgDiskWriteTime"]));
return;
}
}
}
catch (ManagementException e)
{
throw new Exception($"WMI data error: {e.Message}");
}
readTime = writeTime = TimeSpan.Zero;
}
}
public class DiskPerformance
{
// Struktura reprezentująca dane o dysku
[StructLayout(LayoutKind.Sequential)]
public struct DISK_PERFORMANCE
{
public ulong BytesRead;
public ulong BytesWritten;
public uint ReadCount;
public uint WriteCount;
public uint QueueDepth;
public uint ReadTime;
public uint WriteTime;
public uint IdleTime;
public uint ReadTime2;
}
// Importowanie funkcji z biblioteki kernel32.dll
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
ref DISK_PERFORMANCE lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
public static DISK_PERFORMANCE GetDiskPerformance(int diskNumber)
{
DISK_PERFORMANCE perf = new DISK_PERFORMANCE();
IntPtr hDevice = CreateFile(
$@"\\.\PhysicalDrive{diskNumber}",
0,
3, // FILE_SHARE_READ | FILE_SHARE_WRITE
IntPtr.Zero,
3, // OPEN_EXISTING
0,
IntPtr.Zero
);
if (hDevice == IntPtr.Zero)
{
throw new Exception("Failed to open disk");
}
uint bytesReturned = 0;
bool success = DeviceIoControl(
hDevice,
0x00070000, // IOCTL_DISK_PERFORMANCE
IntPtr.Zero,
0,
ref perf,
(uint)Marshal.SizeOf(perf),
ref bytesReturned,
IntPtr.Zero
);
CloseHandle(hDevice);
if (!success)
{
throw new Exception("Failed to retrieve disk performance");
}
return perf;
}
public static double BytesToGB(ulong bytesValue)
{
return bytesValue / Math.Pow(1024, 3);
}
public static double MSToHours(uint msValue)
{
return msValue / (1000.0 * 60 * 60);
}
public static void Main()
{
try
{
var smartInfo = new SmartInfo();
TimeSpan readTime, writeTime;
smartInfo.GetDiskUsageTime(out readTime, out writeTime);
Console.WriteLine($"Czas odczytu dysku: {readTime}");
Console.WriteLine($"Czas zapisu dysku: {writeTime}");
int diskNumber = 0;
DISK_PERFORMANCE diskPerformance = GetDiskPerformance(diskNumber);
Console.WriteLine($"Całkowita ilość odczytanych bajtów: {diskPerformance.BytesRead} B ({BytesToGB(diskPerformance.BytesRead):F2} GB)");
Console.WriteLine($"Całkowita ilość zapisanych bajtów: {diskPerformance.BytesWritten} B ({BytesToGB(diskPerformance.BytesWritten):F2} GB)");
Console.WriteLine($"Całkowita liczba operacji odczytu: {diskPerformance.ReadCount}");
Console.WriteLine($"Całkowita liczba operacji zapisu: {diskPerformance.WriteCount}");
Console.WriteLine($"Całkowity czas pracy dysku: {diskPerformance.ReadTime} ms ({MSToHours(diskPerformance.ReadTime):F2} godzin)");
}
catch (Exception ex)
{
Console.WriteLine($"Wystąpił błąd: {ex.Message}");
}
}
}
I wynik:
Czas odczytu dysku: 00:00:00
Czas zapisu dysku: 00:00:00
Całkowita ilość odczytanych bajtów: 62260 B (0,00 GB)
Całkowita ilość zapisanych bajtów: 1095216660492 B (1020,00 GB)
Całkowita liczba operacji odczytu: 63
Całkowita liczba operacji zapisu: 512
Całkowity czas pracy dysku: 0 ms (0,00 godzin)
Nie tego się spodziewałem.
Skąd ten absurd w odczycie czy czasie pracy dysku?
Z programów komercyjnych wyniki są inne: