使用WMI方式来获取移动磁盘序列号仅支持Vista及以上系统。网上有些资料显示,在XP系统下能够使用WMI获取序列号,我反正试过了都不行。后来在https://msdn.microsoft.com/en-us/library/aa394132(VS.85).aspx证实了这一点!废话少说,直接上代码:
#include <WbemIdl.h>
#include <comdef.h>
#pragma comment(lib,"WbemUuid.lib")
HRESULT GetSerialNumber(void)
{
IWbemServices* pWbemSvc = NULL;
IWbemLocator* pWbemLoc = NULL;
HRESULT hRes;
hRes = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hRes))
{
OutputDebugStr(_T("Failed to initialize COM library!"));
return hRes;
}
hRes = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hRes) && RPC_E_TOO_LATE != hRes)
{
OutputDebugStr(_T("Failed to initialize security!"));
return hRes;
}
hRes = CoCreateInstance(CLSID_WbemLocator, 0, \
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pWbemLoc);
if (FAILED(hRes))
{
OutputDebugStr(_T("Failed to create IWbemLocator object!"));
CoUninitialize();
return hRes;
}
hRes = pWbemLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pWbemSvc // pointer to IWbemServices proxy
);
if (FAILED(hRes))
{
OutputDebugStr(_T("Could not connect!"));
pWbemLoc->Release();
CoUninitialize();
return hRes;
}
hRes = CoSetProxyBlanket(
pWbemSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hRes))
{
OutputDebugStr(_T("Could not set proxy blanket!"));
pWbemSvc->Release();
pWbemLoc->Release();
CoUninitialize();
return hRes;
}
USES_CONVERSION;
VARIANT vtProp;
ULONG uRet = 0;
IEnumWbemClassObject* pEnumClsObj = NULL;
IWbemClassObject* pWbemClsObj = NULL;
CComBSTR strQuery("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
hRes = pWbemSvc->ExecQuery(CComBSTR("WQL"), strQuery, \
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, \
0, &pEnumClsObj);
if (FAILED(hRes))
{
OutputDebugStr(_T("Failed to ExecQuery!"));
if (pEnumClsObj != NULL)
{
pEnumClsObj->Release();
}
pWbemSvc->Release();
pWbemLoc->Release();
CoUninitialize();
return hRes;
}
VariantInit(&vtProp);
CStringArray strArray1;
CStringArray strArray2;
CStringArray strArray3;
while (SUCCEEDED(pEnumClsObj->Next(WBEM_INFINITE, 1, &pWbemClsObj, &uRet)))
{
if (uRet <= 0)
{
break;
}
//获取物理磁盘号:\\.\PHYSICALDRIVE0
hRes = pWbemClsObj->Get(CComBSTR(_T("DeviceID")), 0, &vtProp, 0, 0);
strArray1.Add(AnalizeVariant(&vtProp));
VariantClear(&vtProp);
//获取磁盘名称
hRes = pWbemClsObj->Get(CComBSTR(_T("Model")), 0, &vtProp, 0, 0);
strArray2.Add(AnalizeVariant(&vtProp));
VariantClear(&vtProp);
//获取磁盘序列号
hRes = pWbemClsObj->Get(CComBSTR(_T("SerialNumber")), 0, &vtProp, 0, 0);
strArray3.Add(AnalizeVariant(&vtProp));
VariantClear(&vtProp);
}
VariantClear(&vtProp);
if (pEnumClsObj != NULL)
{
pEnumClsObj->Release();
pEnumClsObj = NULL;
}
if (pWbemClsObj != NULL)
{
pWbemClsObj->Release();
pWbemClsObj = NULL;
}
pWbemSvc->Release();
pWbemLoc->Release();
CoUninitialize();
return S_OK;
}
以上代码已在Win7 + VS 2008上测试通过。