SMBIOS 读取

详见DumpSMBIOS源码,此处只是对修改的部分代码进行一个总结,关键代码的整理

结构体对齐

在DumpSMBIOS示例中,SMBIOS读取的数据有13种类型,每种都对应结构体,并使用
#pragma pack 对齐字节,对齐字节获取数据在Windows API中很常见。
也难怪面试总有人喜欢问数据类型占几个字节的问题,
在通信方面,结构体对齐读取数据流应该方便得多。

#pragma pack(push)
#pragma pack(1)

#define WAKEUP_TYPE_COUNT   9
#define BOARD_TYPE_COUNT    13
typedef struct _RawSMBIOSData
{
    BYTE	Used20CallingMethod;
    BYTE	MajorVersion;
    BYTE	MinorVersion;
    BYTE	DmiRevision;
    DWORD	Length;
    PBYTE	SMBIOSTableData;
} RawSMBIOSData, *PRawSMBIOSData;

typedef struct _SMBIOSHEADER_
{
    BYTE Type;
    BYTE Length;
    WORD Handle;
} SMBIOSHEADER, *PSMBIOSHEADER;

typedef struct _TYPE_0_ {
    SMBIOSHEADER	Header;
    UCHAR	Vendor;
    UCHAR	Version;
    UINT16	StartingAddrSeg;
    UCHAR	ReleaseDate;
    UCHAR	ROMSize;
    ULONG64 Characteristics;
    UCHAR	Extension[2]; // spec. 2.3
    UCHAR	MajorRelease;
    UCHAR	MinorRelease;
    UCHAR	ECFirmwareMajor;
    UCHAR	ECFirmwareMinor;
} BIOSInfo, *PBIOSInfo;

typedef struct _TYPE_1_ {
    SMBIOSHEADER	Header;
    UCHAR	Manufacturer;
    UCHAR	ProductName;
    UCHAR	Version;
    UCHAR	SN;
    UCHAR	UUID[16];
    UCHAR	WakeUpType;
    UCHAR	SKUNumber;
    UCHAR	Family;
} SystemInfo, *PSystemInfo;

typedef struct _TYPE_2_ {
    SMBIOSHEADER	Header;
    UCHAR	Manufacturer;
    UCHAR	Product;
    UCHAR	Version;
    UCHAR	SN;
    UCHAR	AssetTag;
    UCHAR	FeatureFlags;
    UCHAR	LocationInChassis;
    UINT16	ChassisHandle;
    UCHAR	Type;
    UCHAR	NumObjHandle;
    UINT16	*pObjHandle;
} BoardInfo, *PBoardInfo;

typedef struct _TYPE_3_ {
    SMBIOSHEADER Header;
    UCHAR	Manufacturer;
    UCHAR	Type;
    UCHAR	Version;
    UCHAR	SN;
    UCHAR	AssetTag;
    UCHAR	BootupState;
    UCHAR	PowerSupplyState;
    UCHAR	ThermalState;
    UCHAR	SecurityStatus;
    ULONG32	OEMDefine;
    UCHAR	Height;
    UCHAR	NumPowerCord;
    UCHAR	ElementCount;
    UCHAR	ElementRecordLength;
    UCHAR	pElements;
} SystemEnclosure, *PSystemEnclosure;

typedef struct _TYPE_4_ {
    SMBIOSHEADER Header;
    UCHAR	SocketDesignation;
    UCHAR	Type;
    UCHAR	Family;
    UCHAR	Manufacturer;
    ULONG64 ID;
    UCHAR	Version;
    UCHAR	Voltage;
    UINT16	ExtClock;
    UINT16	MaxSpeed;
    UINT16	CurrentSpeed;
    UCHAR   Status;
    UCHAR   ProcessorUpgrade;
    UINT16  L1CacheHandle;
    UINT16  L2CacheHandle;
    UINT16  L3CacheHandle;
    UCHAR   SerialNumber;
    UCHAR   AssertTag;
    UCHAR   PartNumber;
    UCHAR   CoreCount;
    UCHAR   CoreEnabled;
    UCHAR   ThreadCount;
    UINT16  ProcessorCharacteristics;
    UINT16  ProcessorFamily2;

} ProcessorInfo, *PProcessorInfo;

typedef struct _TYPE_5_ {
    SMBIOSHEADER Header;
    // Todo, Here

} MemCtrlInfo, *PMemCtrlInfo;

typedef struct _TYPE_6_ {
    SMBIOSHEADER Header;
    UCHAR	SocketDesignation;
    UCHAR	BankConnections;
    UCHAR	CurrentSpeed;
    // Todo, Here
} MemModuleInfo, *PMemModuleInfo;

typedef struct _TYPE_7_ {
    SMBIOSHEADER Header;
    UCHAR	SocketDesignation;
    UINT16	Configuration;
    UINT16	MaxSize;
    UINT16	InstalledSize;
    UINT16	SupportSRAMType;
    UINT16	CurrentSRAMType;
    UCHAR	Speed;
    UCHAR	ErrorCorrectionType;
    UCHAR	SystemCacheType;
    UCHAR	Associativity;
} CacheInfo, *PCacheInfo;

typedef struct _TYPE_11_ {
    SMBIOSHEADER Header;
    UCHAR	Count;
} OemString, *POemString;

typedef struct _TYPE_17_ {
    SMBIOSHEADER Header;
    UINT16	PhysicalArrayHandle;
    UINT16	ErrorInformationHandle;
    UINT16	TotalWidth;
    UINT16	DataWidth;
    UINT16	Size;
    UCHAR	FormFactor;
    UCHAR	DeviceSet;
    UCHAR	DeviceLocator;
    UCHAR	BankLocator;
    UCHAR	MemoryType;
    UINT16	TypeDetail;
    UINT16	Speed;
    UCHAR	Manufacturer;
    UCHAR	SN;
    UCHAR	AssetTag;
    UCHAR	PN;
    UCHAR	Attributes;
} MemoryDevice, *PMemoryDevice;

typedef struct _TYPE_19_ {
    SMBIOSHEADER Header;
    ULONG32	Starting;
    ULONG32	Ending;
    UINT16	Handle;
    UCHAR	PartitionWidth;
} MemoryArrayMappedAddress, *PMemoryArrayMappedAddress;

typedef struct _TYPE_21_ {
    SMBIOSHEADER Header;
    UCHAR Type;
    UCHAR Interface;
    UCHAR NumOfButton;
} BuiltinPointDevice, *PBuiltinPointDevice;

typedef struct _TYPE_22_ {
    SMBIOSHEADER Header;
    UCHAR	Location;
    UCHAR	Manufacturer;
    UCHAR	Date;
    UCHAR	SN;
    UCHAR	DeviceName;
    UCHAR   Chemistry;
    UINT16  DesignCapacity;
    UINT16  DesignVoltage;
    UCHAR   SBDSVersionNumber;
    UCHAR   MaximumErrorInBatteryData;
    UINT16  SBDSSerialNumber;
    UINT16	SBDSManufactureDate;
    UCHAR   SBDSDeviceChemistry;
    UCHAR   DesignCapacityMultiplie;
    UINT32  OEM;
} PortableBattery, *PPortableBattery;
#pragma pack(pop)

读取SMBIOS数据

DumpSMBIOS使用两种方式读取SMBIOS数据
GetSystemFirmwareTableWMI

GetSystemFirmwareTable

使用 GetSystemFirmwareTable 函数读取原始 SMBIOS 固件表

void Lib_Smbios::initialization()
{
    //	GET_SYSTEM_FIRMWARE_TABLE pGetSystemFirmwareTable = (GET_SYSTEM_FIRMWARE_TABLE)GetProcAddress(GetModuleHandle(L"kernel32"), "GetSystemFirmwareTable");

    LPBYTE pBuff = NULL;

    PBYTE tableStart = nullptr;
    UINT nTableLength = 0;
    DWORD needBufferSize = 0;


    const DWORD Signature = 'RSMB';
#if 0
    DWORD Signature = 'R';
    Signature = (Signature << 8) + 'S';
    Signature = (Signature << 8) + 'M';
    Signature = (Signature << 8) + 'B';
#endif

    //从固件表提供程序检索指定的固件表。
    //https://learn.microsoft.com/zh-cn/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemfirmwaretable
    needBufferSize = GetSystemFirmwareTable(Signature, 0, NULL, 0);
    pBuff = new BYTE[needBufferSize];

    needBufferSize = GetSystemFirmwareTable(Signature, 0,pBuff,needBufferSize);
    if (needBufferSize > 0) {
        const PRawSMBIOSData pDMIData = (PRawSMBIOSData)pBuff;
        MajorVersion = pDMIData->MajorVersion;
        MinorVersion = pDMIData->MinorVersion;
        DMIRevision = pDMIData->DmiRevision;

        tableStart = (PBYTE) & (pDMIData->SMBIOSTableData);
        nTableLength = pDMIData->Length;
    }

    if ((0 == needBufferSize) || (nTableLength > needBufferSize))
    {
        if (getWmiSmbios(&pBuff, &nTableLength))
            tableStart = pBuff;
    }

    if (tableStart)
        ParseSMBIOSStruct(tableStart, nTableLength);

    if (pBuff)
        delete[] pBuff;
}
WMI

使用 WMI 检索 SMBIOS 属性。 Win32 类中包含许多单独的属性。 还可以使用 MSSMBios_RawSMBiosTables 类在单个缓冲区中检索原始 SMBIOS 数据。

bool Lib_Smbios::getWmiSmbios(BYTE ** data, UINT * length)
{
    IWbemServices *  pSvc = NULL;
    IWbemServices *  pSvcSmbios = NULL;
    IWbemLocator *   pLoc = NULL;
    HRESULT            result;
    IEnumWbemClassObject *  pEnumerator = NULL;
    std::wostringstream     query;
    std::wstring            q;
    IWbemClassObject *      pInstance = NULL;
    VARIANT                 vtProp;
    ULONG                   uReturn = 0;
    CIMTYPE                 pvtType;

    result = CoInitialize(NULL);

    if (!SUCCEEDED(result))
        return false;

    result = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (!SUCCEEDED(result)) {
        CoUninitialize();
        return false;
    }

    result = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);
    if (!SUCCEEDED(result)) {
        CoUninitialize();
        return false;
    }

    result = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
    if (!SUCCEEDED(result)) {
        pLoc->Release();
        CoUninitialize();
        return false;
    }

    result = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
    if (!SUCCEEDED(result)) {
        pLoc->Release();
        CoUninitialize();
        return false;
    }

    result = pLoc->ConnectServer(_bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pSvcSmbios);
    if (!SUCCEEDED(result)) {
        pLoc->Release();
        CoUninitialize();
        return false;
    }

    result = CoSetProxyBlanket(pSvcSmbios, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
    if (!SUCCEEDED(result)) {
        pSvcSmbios->Release();
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
    }

    result = pSvcSmbios->CreateInstanceEnum(bstr_t(L"MSSMBios_RawSMBiosTables"), 0, NULL, &pEnumerator);
    if (SUCCEEDED(result)) {
        while (pEnumerator) {
            result = pEnumerator->Next(WBEM_INFINITE, 1, &pInstance, &uReturn);

            if (!uReturn) {
                break;
            }
            VariantInit(&vtProp);
            result = pInstance->Get(bstr_t("SMBiosData"), 0, &vtProp, &pvtType, NULL);
            if (SUCCEEDED(result)) {
                SAFEARRAY * array = V_ARRAY(&vtProp);

                *length = array->rgsabound[0].cElements;
                *data = new BYTE[*length];
                memcpy(*data, (BYTE*)array->pvData, *length);
                VariantClear(&vtProp);
            }
        }
        pEnumerator->Release();
        if (pInstance)
            pInstance->Release();
    }

    if (pSvcSmbios)
        pSvcSmbios->Release();
    if (pSvc)
        pSvc->Release();
    if (pLoc)
        pLoc->Release();

    CoUninitialize();
    return true;
}

自定义结构体 - 实际获取数据结构

DumpSMBIOS项目中打印的字段封装成结构体,转换数据时保存,不只是输出内容

#pragma region "获取 SMBIOS 指定数据(指定结构转换)" {

typedef struct _W_TYPE_0_ {
    PWCHAR Vendor;
    PWCHAR Version;
    PWCHAR Date;
    //pBIOS->Header.Length > 0x14
    DWORD SysVersion=0;
    DWORD ECVersion=0;
}W_BIOSInfo;

typedef struct _W_TYPE_1_
{
    PWCHAR Manufactor;
    PWCHAR ProductName;
    PWCHAR Version;
    PWCHAR SerialNumber;
    //pSystem->Header.Length > 0x08
    UUID SysUUID;
    //pSystem->Header.Length > 0x19
    PWCHAR SysSKU;
    PWCHAR SysFamily;
}W_SystemInfo;

typedef struct _W_TYPE_2_
{
    PWCHAR Manufacturer;
    PWCHAR Product;
    PWCHAR Version;
    PWCHAR SN;
    PWCHAR AssetTag;
    UCHAR FeatureFlags;
    //pBoard->Header.Length > 0x08
    PWCHAR LocationInChassis;
    //pBoard->Header.Length > 0x0B
    PWCHAR BoardType;
}W_BoardInfo;

typedef struct _W_TYPE_3_
{
    PWCHAR Manufacturer;
    PWCHAR Version;
    PWCHAR SN;
    PWCHAR AssetTag;
}W_SystemEnclosure;

typedef struct _W_TYPE_4_
{
    PWCHAR SocketDesignation;
    PWCHAR ProcessType;
    PWCHAR Family;
    PWCHAR Manufacturer;

    PWCHAR Version;
    PWCHAR Voltage;
    UINT16	ExtClock;
    UINT16	MaxSpeed;
    UINT16	CurrentSpeed;
    UCHAR   Status;

}W_ProcessorInfo;


typedef struct _W_TYPE_6_
{
    PWCHAR SocketDesignation;
    PWCHAR BankConnections;
    quint64 CurrentSpeed;

} W_MemModuleInfo;


typedef struct _W_TYPE_7_
{
    PWCHAR SocketDesignation;

} W_CacheInfo;

typedef struct _W_TYPE_11_
{
    QList<PWCHAR> datas;

} W_OemString;

typedef struct _W_TYPE_17_
{
    quint64 TotalWidth;
    quint64 DataWidth;
    PWCHAR  DeviceLocator;
    PWCHAR  BankLocator;
    PWCHAR  MemoryType;
    //pMD->Header.Length > 0x15
    quint64 Speed;
    PWCHAR	Manufacturer;
    PWCHAR	SN;
    PWCHAR	AssetTag;
    PWCHAR	PN;
    quint64 Size;

} W_MemoryDevice;


typedef struct _W_TYPE_21_
{
    PWCHAR  BuiltinPointDeviceType;
    PWCHAR  BuiltinPointDeviceInterface;
    quint64  NumOfButton;

} W_BuiltinPointDevice;


typedef struct _W_TYPE_22_
{
    PWCHAR Location;
    PWCHAR Manufacturer;
    //pPB->Date != 0
    PWCHAR Date;
    //pPB->SN != 0
    PWCHAR SN;

    PWCHAR DeviceName;

    //(pPB->Chemistry != 2)
    PWCHAR Chemistry;
    PWCHAR SBDSDeviceChemistry;

    quint64 DesignCapacity;
    quint64 DesignCapacityMultiplie;
    quint64 DesignVoltage;
    PWCHAR SBDSVersionNumber;
    quint64 MaximumErrorInBatteryData;
    quint64 SBDSSerialNumber;

} W_PortableBattery;

#pragma endregion }

结构体数据转换

其中需要注意的是 CP_ACP 与 CP_OEMCP 的使用,
测试时使用CP_OEMCP数据乱码,
但是 DumpSMBIOS 项目中使用 CP_OEMCP输出正常,脑壳痛。

static const char* LocateStringA(const char* str, UINT i)
{
    static const char strNull[] = "";

    if (0 == i || 0 == *str) return strNull;

    while (--i)
    {
        str += strlen((char*)str) + 1;
    }
    return str;
}

#define GetData(_STR_,_IN_VAL_,_OUT_VAL_,val)                                       \
{                                                                                   \
    const char* c_##val = LocateStringA(_STR_, _IN_VAL_);                           \
    const int n_##val = (int) strlen(c_##val);                                      \
    _OUT_VAL_= new WCHAR[n_##val + 1];                                              \
    if (_OUT_VAL_)                                                                  \
{                                                                               \
    SecureZeroMemory(_OUT_VAL_, sizeof(WCHAR) * (n_##val + 1));                 \
    MultiByteToWideChar(CP_ACP, NULL, c_##val, n_##val, _OUT_VAL_, n_##val + 1);\
    }                                                                               \
    }

//将UChat转换为PWCHAR数据
bool Lib_Smbios::ProcBIOSInfo(Lib_Smbios* T, void* p)
{
    PBIOSInfo pBIOS = (PBIOSInfo)p;
    const char* str = toPointString(p);
    //后面使用宏定义 GetData 替换此处代码
    //    const char* Vendor = LocateStringA(str, pBIOS->Vendor);
    //    const char* Version = LocateStringA(str, pBIOS->Version);
    //    const char* Date = LocateStringA(str, pBIOS->ReleaseDate);
    //    const int nVendor = (int) strlen(Vendor);
    //    const int nVersion = (int) strlen(Version);
    //    const int nDate = (int) strlen(Date);

    //    T->DATA_BIOSInfo.Vendor= new WCHAR[nVendor + 1];
    //    T->DATA_BIOSInfo.Version= new WCHAR[nVersion + 1];
    //    T->DATA_BIOSInfo.Date= new WCHAR[nDate + 1];

    //    if (T->DATA_BIOSInfo.Vendor)
    //    {
    //        SecureZeroMemory(T->DATA_BIOSInfo.Vendor, sizeof(WCHAR) * (nVendor + 1));
    //        MultiByteToWideChar(CP_ACP, NULL, Vendor, nVendor, T->DATA_BIOSInfo.Vendor, nVendor + 1);
    //    }
    //    if (T->DATA_BIOSInfo.Version)
    //    {
    //        SecureZeroMemory(T->DATA_BIOSInfo.Version, sizeof(WCHAR) * (nVersion + 1));
    //        MultiByteToWideChar(CP_ACP, NULL, Version, nVersion, T->DATA_BIOSInfo.Version, nVersion + 1);
    //    }
    //    if (T->DATA_BIOSInfo.Date)
    //    {
    //        SecureZeroMemory(T->DATA_BIOSInfo.Date, sizeof(WCHAR) * (nDate + 1));
    //        MultiByteToWideChar(CP_ACP, NULL, Date, nDate, T->DATA_BIOSInfo.Date, nDate + 1);
    //    }

    GetData(str,pBIOS->Vendor,T->DATA_BIOSInfo.Vendor,Vendor);
    GetData(str,pBIOS->Version,T->DATA_BIOSInfo.Version,Version);
    GetData(str,pBIOS->ReleaseDate,T->DATA_BIOSInfo.Date,Date);

    if (pBIOS->Header.Length > 0x14)
    {
        T->DATA_BIOSInfo.SysVersion = pBIOS->MajorRelease << 16 | pBIOS->MinorRelease;
        T->DATA_BIOSInfo.ECVersion = pBIOS->ECFirmwareMajor << 16 | pBIOS->ECFirmwareMinor;
    }



if(Isprint){
    _tprintf(TEXT("%s\n"), getHeaderString(0));
    _tprintf(TEXT("Vendor: %s\n"), T->DATA_BIOSInfo.Vendor);
    _tprintf(TEXT("Version: %s\n"), T->DATA_BIOSInfo.Version);
    _tprintf(TEXT("BIOS Starting Segment: 0x%X\n"), pBIOS->StartingAddrSeg);
    _tprintf(TEXT("Release Date: %s\n"), T->DATA_BIOSInfo.Date);
    _tprintf(TEXT("Image Size: %dK\n"), (pBIOS->ROMSize + 1) * 64);
    if (pBIOS->Header.Length > 0x14)
    {   // for spec v2.4 and later
        _tprintf(TEXT("System BIOS version: %d.%d\n"), pBIOS->MajorRelease, pBIOS->MinorRelease);
        _tprintf(TEXT("EC Firmware version: %d.%d\n"), pBIOS->ECFirmwareMajor, pBIOS->ECFirmwareMinor);
    }
}


    return true;
}

参考示例链接

【SMBIOS数据结构和信息】读取参考示例链接:
https://github.com/KunYi/DumpSMBIOS
SMBIOS获取system bios ec cpu memory等相关信息
SMBIOS 规范定义了将进入与系统相关的数据结构的数据结构和信息
SMBIOS | DMTF规范

QT CMD命令行输出

之前看到某些软件既可以CMD命令行输出数据,又可以打开界面操作的时候,我就尝试过使用QT实现类似的功能。
通过console控制台程序与可执行程序放在同级目录实现,如果argc参数个数大于1就是console打印数据,否则就打开同级目录下的可执行程序,但是这样一来启动的可执行程序的时候始终会有console控制台程序一闪而逝。这个问题始终没有解决、、、

其他方法 隐藏控制台窗体

通过在main.cpp添加这段,确实能隐藏console打开,但是需要的console输出内容就没了,这只适用于隐藏不显示console控制台。

//Qt 隐藏控制台窗体
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

通过ShowWindow隐藏控制台也只是加快了隐藏的速度,还是能看见console控制台程序一闪而逝。

  HWND consoleWindow = GetConsoleWindow(); // 获取控制台窗口句柄
  // 隐藏窗口
  ShowWindow(consoleWindow, SW_HIDE);

值得注意的是如果需要打印数据后自动退出程序就需要修改main的返回值
完整示例:

//Qt 隐藏控制台窗体
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    if(argc==1)
    {
        HWND consoleWindow = GetConsoleWindow(); // 获取控制台窗口句柄
        // 隐藏窗口
        ShowWindow(consoleWindow, SW_HIDE);

        QProcess* process=new QProcess();
        process->startDetached("Computer_INFO.exe");
        process->waitForStarted(-1);
    }
    else
    {
        Lib_Command_Out out;
        out.OpeaType(argc, argv);
    }

    //退出事件循环
    //https://blog.csdn.net/qq_21078557/article/details/89959755
    a.exit(0);
    return 0;
    //    return a.exec();
}

可执行程序示例 :

CMD输入示例:

SMBIOS数据查询小工具命令行:
================================
*-V                       显示命令行参数
 -S [-I] [filepath]          打印出SMBIOS的所有详细信息,具体内容参考GitHub上DumpSMBIOS开源项目,
                             可选参数[-I] 输出INI格式文件 ,
                             可选参数[filepath] 设置输出路径,没有则默认exe路径中生成[SMBIOS.INI]文件
 -D [-I] [filepath]          打印硬盘相关信息[同上可选]
 -VS [-I] [filepath]         打印卷/盘符相关信息[同上可选]*

///C:\Users\admin\Desktop\SMBIOS_READ.exe -v 输出:

==========          BIOS information           ==========
Vendor: American Megatrends Inc.
Version: 1005
BIOS Starting Segment: 0xF000
Release Date: 08/07/2019
Image Size: 16384K
System BIOS version: 5.12
EC Firmware version: 255.255
==========         System information          ==========
Manufacturer: System manufacturer
Product Name: System Product Name
Version: System Version
Serial Number: System Serial Number
UUID: F9824375-C4FB-4D1E-E715-D45D641D7A2A
Wake-up Type: Power Switch
SKU Number: SKU
Family: To be filled by O.E.M.
==========       Base Board information        ==========
Length: 0xF
Manufacturer: ASUSTeK COMPUTER INC.
Product Name: PRIME H310M-K R2.0
Version: Rev X.0x
Serial Number: 191262638910697
Asset Tag Number: Default string
Feature Flag: 0x9
Location in Chassis: Default string
Board Type: Processor/Memory Module
Number of Contained Object Handles: 0
Object Handles:

==========    System Enclosure information     ==========
Length: 0x16
Manufacturer: Default string
Version: Default string
Serial Number: Default string
Asset Tag Number: Default string
==========             OEM String              ==========
Count: 8
OEM String1: Default string
OEM String2: Default string
OEM String3: OLEANDER V2
OEM String4: Default string
OEM String5: FFFFFFFFFFFFF
OEM String6: FFFFFFFFFFFFF
OEM String7: FFFFFFFFFFFFF
OEM String8: Default string
==========            Memory Device            ==========
Length: 0x28
Total Width: 64bits
Data Width: 64bits
Device Locator: ChannelA-DIMM1
Bank Locator: BANK 0
Memory Type: DDR4
Size: 8192M
Speed: 2666
Manufacturer: CRUCIAL
Serial Number: 22AD9C80
Asset Tag Number: 9876543210
Part Number: CT8G4DFS8266.M8FE
==========            Memory Device            ==========
Length: 0x28
Total Width: 64bits
Data Width: 64bits
Device Locator: ChannelB-DIMM1
Bank Locator: BANK 2
Memory Type: DDR4
Size: 8192M
Speed: 2666
Manufacturer: CRUCIAL
Serial Number: 25ACA8B3
Asset Tag Number: 9876543210
Part Number: CT8G4DFS8266.M8FD
==========     Memory Array Mapped Address     ==========
Length: 0x1F
Starting Address: 0x00000000
Ending Address: 0x00FFFFFF
Memory Array Handle: 0x36
Partition Width: 0x2
==========           Cache information         ==========
Length: 0x1B
Socket Designation: L1 Cache
==========           Cache information         ==========
Length: 0x1B
Socket Designation: L2 Cache
==========           Cache information         ==========
Length: 0x1B
Socket Designation: L3 Cache
==========        Processor information        ==========
Length: 0x30
Socket Designation: LGA1151
Processor Type: Math Processor
Processor Family: 
Processor ID:
Processor Manufacturer: Intel(R) Corporation
Processor Voltage: es|ES|iso8859-1
Processor Version: Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz
External Clock: 100MHz, 0MHz is unknown clock
Max Speed: 8300MHz
Current Speed: 2900MHz
Status: 0x41

双击打开 -执行程序:
Qt 使用WINDOWS API读取SMBIOS信息,并通过CMD命令打印相关信息,参考DumpSMBIOS项目-LMLPHP

01-12 04:49