正如标题所说,我正在vb.net中工作并尝试在文本框中获取我的硬盘的RPM。 接下来我想弄清楚我的磁盘是硬盘还是SSD。
我已经在网上搜索了一整周我能想到的任何东西,而我能找到的就是温度读数:
Const TEMPERATURE_ATTRIBUTE As Byte = 115
Public Function GetDriveTemp() As String
Dim retval As String = "Temp: "
Try
Dim searcher As New ManagementObjectSearcher("root\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData")
'loop through all the hard disks
For Each queryObj As ManagementObject In searcher.[Get]()
Dim arrVendorSpecific As Byte() = DirectCast(queryObj.GetPropertyValue("VendorSpecific"), Byte())
'Find the temperature attribute
Dim tempIndex As Integer = Array.IndexOf(arrVendorSpecific, TEMPERATURE_ATTRIBUTE)
retval = (arrVendorSpecific(tempIndex + 5))
Next
Catch err As ManagementException
Console.WriteLine("An error occurred while querying for WMI data: " + err.Message)
End Try
Return retval
End Function
我知道Byte 115是hdd temp,但我无法找出所有其他字节代表的内容。 有人有什么想法吗?
我需要知道如何搜索普通硬盘没有的SSD特定值。 我知道有,但我似乎找不到任何东西。
接下来我需要找出RPM是什么(不是ssd)
答案 0 :(得分:4)
这些天似乎有更好的方法(C#):
using (var partitionSearcher = new ManagementObjectSearcher(
@"\\localhost\ROOT\Microsoft\Windows\Storage",
$"SELECT DiskNumber FROM MSFT_Partition WHERE DriveLetter='{upperCaseDiskLetter}'"))
{
var partition = partitionSearcher.Get().Cast<ManagementBaseObject>().Single();
using (var physicalDiskSearcher = new ManagementObjectSearcher(
@"\\localhost\ROOT\Microsoft\Windows\Storage",
$"SELECT Size, Model, MediaType FROM MSFT_PhysicalDisk WHERE DeviceID='{ partition["DiskNumber"] }'"))
{
var physicalDisk = physicalDiskSearcher.Get().Cast<ManagementBaseObject>().Single();
var isSsd =
(UInt16)physicalDisk["MediaType"] == 4 ||
SSDModelSubstrings.Any(substring => result.Model.ToLower().Contains(substring)); ;
}
}
基于相同的底层类型,但在PowerShell中稍微简单一些:
$is_disk_C_SSD = (Get-PhysicalDisk | ?{$_.DeviceId -eq (Get-Partition -DriveLetter 'C')[0].DiskNumber})[0].MediaType -eq 'SSD'
答案 1 :(得分:1)
解决了它。
如果有人需要知道
使用Visual Studio创建包含以下代码的dll:
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace DetectSsd
{
public class Program
{
// For CreateFile to get handle to drive
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint FILE_SHARE_READ = 0x00000001;
public const uint FILE_SHARE_WRITE = 0x00000002;
public const uint OPEN_EXISTING = 3;
public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
// CreateFile to get handle to drive
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateFileW(
[MarshalAs(UnmanagedType.LPWStr)]
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
// For control codes
public const uint FILE_DEVICE_MASS_STORAGE = 0x0000002d;
public const uint IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
public const uint FILE_DEVICE_CONTROLLER = 0x00000004;
public const uint IOCTL_SCSI_BASE = FILE_DEVICE_CONTROLLER;
public const uint METHOD_BUFFERED = 0;
public const uint FILE_ANY_ACCESS = 0;
public const uint FILE_READ_ACCESS = 0x00000001;
public const uint FILE_WRITE_ACCESS = 0x00000002;
public static uint CTL_CODE(uint DeviceType, uint Function,
uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) |
(Function << 2) | Method);
}
// For DeviceIoControl to check no seek penalty
public const uint StorageDeviceSeekPenaltyProperty = 7;
public const uint PropertyStandardQuery = 0;
[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_PROPERTY_QUERY
{
public uint PropertyId;
public uint QueryType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] AdditionalParameters;
}
[StructLayout(LayoutKind.Sequential)]
public struct DEVICE_SEEK_PENALTY_DESCRIPTOR
{
public uint Version;
public uint Size;
[MarshalAs(UnmanagedType.U1)]
public bool IncursSeekPenalty;
}
// DeviceIoControl to check no seek penalty
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl",
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint dwIoControlCode,
ref STORAGE_PROPERTY_QUERY lpInBuffer,
uint nInBufferSize,
ref DEVICE_SEEK_PENALTY_DESCRIPTOR lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
// For DeviceIoControl to check nominal media rotation rate
public const uint ATA_FLAGS_DATA_IN = 0x02;
[StructLayout(LayoutKind.Sequential)]
public struct ATA_PASS_THROUGH_EX
{
public ushort Length;
public ushort AtaFlags;
public byte PathId;
public byte TargetId;
public byte Lun;
public byte ReservedAsUchar;
public uint DataTransferLength;
public uint TimeOutValue;
public uint ReservedAsUlong;
public IntPtr DataBufferOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] PreviousTaskFile;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] CurrentTaskFile;
}
[StructLayout(LayoutKind.Sequential)]
public struct ATAIdentifyDeviceQuery
{
public ATA_PASS_THROUGH_EX header;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public ushort[] data;
}
// DeviceIoControl to check nominal media rotation rate
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl",
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint dwIoControlCode,
ref ATAIdentifyDeviceQuery lpInBuffer,
uint nInBufferSize,
ref ATAIdentifyDeviceQuery lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
// For error message
public const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint FormatMessage(
uint dwFlags,
IntPtr lpSource,
uint dwMessageId,
uint dwLanguageId,
StringBuilder lpBuffer,
uint nSize,
IntPtr Arguments);
static void Main(string[] args)
{
HasNominalMediaRotationRate();
}
// Method for nominal media rotation rate
// (Administrative privilege is required)
public static string HasNominalMediaRotationRate()
{
SafeFileHandle hDrive = CreateFileW(
"\\\\.\\PhysicalDrive0",
GENERIC_READ | GENERIC_WRITE, // Administrative privilege is required
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
IntPtr.Zero);
if (hDrive == null || hDrive.IsInvalid)
{
string message = GetErrorMessage(Marshal.GetLastWin32Error());
return("CreateFile failed. " + message);
}
uint IOCTL_ATA_PASS_THROUGH = CTL_CODE(
IOCTL_SCSI_BASE, 0x040b, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS); // From ntddscsi.h
ATAIdentifyDeviceQuery id_query = new ATAIdentifyDeviceQuery();
id_query.data = new ushort[256];
id_query.header.Length = (ushort)Marshal.SizeOf(id_query.header);
id_query.header.AtaFlags = (ushort)ATA_FLAGS_DATA_IN;
id_query.header.DataTransferLength =
(uint)(id_query.data.Length * 2); // Size of "data" in bytes
id_query.header.TimeOutValue = 3; // Sec
id_query.header.DataBufferOffset = (IntPtr)Marshal.OffsetOf(
typeof(ATAIdentifyDeviceQuery), "data");
id_query.header.PreviousTaskFile = new byte[8];
id_query.header.CurrentTaskFile = new byte[8];
id_query.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE
uint retval_size;
bool result = DeviceIoControl(
hDrive,
IOCTL_ATA_PASS_THROUGH,
ref id_query,
(uint)Marshal.SizeOf(id_query),
ref id_query,
(uint)Marshal.SizeOf(id_query),
out retval_size,
IntPtr.Zero);
hDrive.Close();
if (result == false)
{
string message = GetErrorMessage(Marshal.GetLastWin32Error());
return ("DeviceIoControl failed. " + message);
}
else
{
// Word index of nominal media rotation rate
// (1 means non-rotate device)
const int kNominalMediaRotRateWordIndex = 217;
if (id_query.data[kNominalMediaRotRateWordIndex] == 1)
{
return "Disk is SSD";
}
else
{
return "Disk is non SSD";
}
}
}
// Method for error message
public static string GetErrorMessage(int code)
{
StringBuilder message = new StringBuilder(255);
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
IntPtr.Zero,
(uint)code,
0,
message,
(uint)message.Capacity,
IntPtr.Zero);
return message.ToString();
}
}
}
然后在vb.net中使用以下命令调用此dll:
Imports DetectSsd
然后你可以使用以下任何地方调用它:
textbox.text = DetectSsd.Program.HasNominalMediaRotationRate()
c#的来源:emoacht.wordpress.com/2012/11/06/csharp-ssd
为vb.net编辑
答案 2 :(得分:0)
@ Mr-HaXx当您调用HasNominalMediaRotationRate()时,您需要提供一个驱动器号码。如何知道驱动器C或D是否为驱动器号0,1或2?
我的电脑配有ssd(C)和hdd(D)。
当我用0开始代码时,它告诉我这是一个ROTATE设备。所以它应该是D:驱动器,但想知道我的C驱动器或D驱动器的驱动器数量。
由于
编辑:
此外,这是C#中的代码,用于从逻辑驱动器号中查找物理驱动器号。 (页面底部)