前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Windows查看硬盘总字节数

Windows查看硬盘总字节数

原创
作者头像
Windows技术交流
修改2024-06-06 16:12:39
修改2024-06-06 16:12:39
2810
举报
文章被收录于专栏:Windows技术交流Windows技术交流

Get-PhysicalDisk命令虽然好,但是不适用低版本系统,比如Server2008R2和Win7

代码语言:powershell
复制
Get-PhysicalDisk | Select-Object DeviceID, MediaType, Model, Size

Win32_DiskDrive相关命令虽然兼容Server2008R2-2022(Win7-Win11),但是它获取的总字节数不精确

代码语言:powershell
复制
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代码,获取精确的总字节数

代码语言: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,卸载重启机器没用

代码语言:txt
复制
Get-Process | Where-Object {$_.company -notlike '*Microsoft*' }|select Name,Description,Company

现在没现场了

我卸载了几个软件然后重启机器OK了(一开始卸载的vmware converter没起作用,第2次把另外2个converter也卸载后重启机器就好了)

这个正常机器里也有,我也卸载了

代码语言:txt
复制
虽然卸载了这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服务。

代码语言:txt
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档