Get-PhysicalDisk命令虽然好,但是不适用低版本系统,比如Server2008R2和Win7
Get-PhysicalDisk | Select-Object DeviceID, MediaType, Model, Size
Win32_DiskDrive相关命令虽然兼容Server2008R2-2022(Win7-Win11),但是它获取的总字节数不精确
Get-WmiObject -Query "SELECT * FROM Win32_DiskDrive"
Get-WmiObject -Class Win32_DiskDrive | Select-Object DeviceID,Size
(Get-WmiObject -Class Win32_DiskDrive | Where-Object { $_.DeviceID -eq '\\.\PHYSICALDRIVE0' }).Size
获取磁盘总字节数(详细看图中彩色标注)
兼容Server2008R2-2025(Win7-Win11)的直接一两句命令查遍了,没有
但是我看到diskgenius等第三方软件可以获取到精确的总字节数,想着肯定有代码能实现(肯定不是一两句)
这里分享一个兼容Server2008R2-2022(Win7-Win11)的通用powershell代码,获取精确的总字节数
#ps1
#compatible within:win7-win11、server2008r2-2025
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class NativeMethods_new
{
public const uint GENERIC_READ = (0x80000000);
public const uint OPEN_EXISTING = 3;
public const uint IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = 0x000700A0;
public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", SetLastError = true)]
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,
IntPtr lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
public struct DiskGeometry
{
public long Cylinders;
public int MediaType;
public int TracksPerCylinder;
public int SectorsPerTrack;
public int BytesPerSector;
// Possibly more fields depending on the exact definition of DISK_GEOMETRY
}
[StructLayout(LayoutKind.Sequential)]
internal struct DiskGeometryEx
{
public DiskGeometry Geometry;
public long DiskSize;
public byte Data;
// For simplicity, assuming 'Data' is a placeholder for additional data.
// The actual structure may include a fixed buffer or other fields.
}
}
public class DriveSizeFetcher_new
{
public long GetDriveSize(string drivePath)
{
IntPtr diskHandle = NativeMethods_new.CreateFile(drivePath, 0, 7, IntPtr.Zero, NativeMethods_new.OPEN_EXISTING, 0, IntPtr.Zero);
if (diskHandle == NativeMethods_new.INVALID_HANDLE_VALUE || diskHandle == IntPtr.Zero)
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
try
{
long size = -1;
uint numBytesRead = 0;
int geometrySize = Marshal.SizeOf(typeof(NativeMethods_new.DiskGeometryEx));
IntPtr geometryBlob = Marshal.AllocHGlobal(geometrySize);
try
{
bool success = NativeMethods_new.DeviceIoControl(diskHandle, NativeMethods_new.IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, IntPtr.Zero, 0, geometryBlob, (uint)geometrySize, ref numBytesRead, IntPtr.Zero);
if (success)
{
NativeMethods_new.DiskGeometryEx geometry = (NativeMethods_new.DiskGeometryEx)Marshal.PtrToStructure(geometryBlob, typeof(NativeMethods_new.DiskGeometryEx));
size = geometry.DiskSize;
}
else
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
Marshal.FreeHGlobal(geometryBlob);
}
return size;
}
finally
{
NativeMethods_new.CloseHandle(diskHandle);
}
}
}
"@ -Language CSharp
# Instantiate the DriveSizeFetcher_new class
$DriveSizeFetcher_new = New-Object DriveSizeFetcher_new
# Get all physical disks using WMI query and sort them by Index
$disks = Get-WmiObject -Query "SELECT * FROM Win32_DiskDrive" | Sort-Object Index
foreach ($disk in $disks)
{
try {
# Get the drive size in bytes
Write-Host "`n$disk"
Write-Host $disk.Index
$size = $DriveSizeFetcher_new.GetDriveSize("\\.\PHYSICALDRIVE" + $disk.Index)
Write-Host "`nDrive $($disk.Index) size: $size bytes" 2>$null
$sizeInGB = $size / 1GB
Write-Host "$size/1024/1024/1024 = $sizeInGB GB`n" 2>$null
} catch {
Write-Error "Failed to get drive size: $_" 2>$null
}
}
这个powershell代码兼容性挺好的,但意外发现在自己一台2008R2上跑的时候,发现获取系统盘磁盘大小时catch到异常,我买了1台新的2008R2测试又正常,不清楚什么原因导致catch异常
发现有vmware converter,卸载重启机器没用
Get-Process | Where-Object {$_.company -notlike '*Microsoft*' }|select Name,Description,Company
现在没现场了
我卸载了几个软件然后重启机器OK了(一开始卸载的vmware converter没起作用,第2次把另外2个converter也卸载后重启机器就好了)
这个正常机器里也有,我也卸载了
虽然卸载了这4个软件了执行脚本不再报错了,但是我在新、老机器把卸载的那几个软件装回去却复现不了问题。
确实就是卸载了这4个软件后重启机器才好的,印象中卸载"Tencent Virtio Driver"的时候报错了,我忽略了,
想不起报的啥了,卸载其他3个converter时没报错。
这4个软件共同点是都有引入内核驱动,可参考https://cloud.tencent.com/developer/article/1957099
https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer
用微软的Process Explorer可以看到内核驱动引入了Citrix xenconvert_v2.4.1引入了2个驱动、VMware-converter-en-6.4.0-21710069引入了1个驱动、还有腾讯云的3个虚拟化驱动,并且有3个vmware服务。
get-service *vmware*, *starwind*, *XenConvert*, *w32time*
至于starwind好像什么也没引入,其实它调用的是vmware的库:
C:\Program Files\StarWind Software\StarWind V2V Converter\lib\vmware-vdiskmanager.exe
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。