WMI Win32_OperatingSystem OSProductSuite在Windows XP上提供了不正确的值
本文关键字:不正确 XP Win32 OperatingSystem OSProductSuite Windows WMI | 更新日期: 2023-09-27 18:24:57
以下C#代码使用WMI从Win32_OperatingSystem获取OsProductSuite值,以及使用WinApi函数GetVersionEx:的类似wSuiteMask
static void Main(string[] args)
{
try
{
var query = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
var name = query.Get()
.OfType<ManagementObject>()
.Single()
.GetPropertyValue("Name");
Console.WriteLine("Name from WMI = {0}", name);
var suite = query.Get()
.OfType<ManagementObject>()
.Single()
.GetPropertyValue("OSProductSuite") ?? "<NULL>";
Console.WriteLine("Suite from WMI = {0}", suite);
var info = new OsVersionInfo()
{
OSVersionInfoSize = Marshal.SizeOf(typeof(OsVersionInfo))
};
var gotVersion = GetVersionEx(ref info);
Console.WriteLine("GetVersionEx gotVersion = {0}", gotVersion);
Console.WriteLine("GetVersionEx ErrorCode = {0}", Marshal.GetLastWin32Error());
Console.WriteLine("Suite from GetVersionEx = {0}", info.SuiteMask);
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
Console.WriteLine("Press any key");
Console.ReadKey();
}
[DllImport("kernel32.dll")]
private static extern bool GetVersionEx(ref OsVersionInfo osVersionInfo);
[StructLayout(LayoutKind.Sequential)]
private struct OsVersionInfo
{
public int OSVersionInfoSize;
public int MajorVersion;
public int MinorVersion;
public int BuildNumber;
public int PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szCSDVersion;
public short ServicePackMajor;
public short ServicePackMinor;
public short SuiteMask;
public byte ProductType;
public byte Reserved;
}
问题:在XP之后的所有操作系统上,WMI和GetVersionEx
都报告正确的OSProductSuite
值。但在Windows XP上,WMI中的OSProductSuite
为空。
我最初认为这是WMI的.NET包装中的一个问题,所以我无耻地改编了示例中的C++代码:从本地计算机获取WMI数据以做同样的事情(更改在步骤7中):
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
int main(int argc, char **argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
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))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root'cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->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 (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT''CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // 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))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_OperatingSystem"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the OSProductSuite property
hr = pclsObj->Get(L"OSProductSuite", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
wcout << L"Failure in WMI";
return 1;
}
wcout << "Variant Type of OSProductSuite from WMI = " << vtProp.vt << endl;
wcout << "OSProductSuite from WMI = " << vtProp.uintVal << endl;
VariantClear(&vtProp);
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
OSVERSIONINFOEX info;
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
auto gotVersion = GetVersionEx((OSVERSIONINFO*)&info);
if (!gotVersion)
{
wcout << L"GetVersionEx error is " << GetLastError();
return 1;
}
wcout << L"wSuiteMask from GetVersionEx = " << info.wSuiteMask;
wcin.peek();
return 0; // Program successfully completed.
}
但OSProductSuite
的变体类型是VARENUM::VT_NULL (1)
,所以问题似乎出在WMI本身。所以,这是WMI的一些XP问题,不是吗?
附言:虽然我使用的XP分发版可能存在一些问题,或者问题源于两台机器都是虚拟的(VmWare和SCVMM),但这似乎相当可疑。
就像大多数WMI类Win32_OperatingSystem被声明为具有一样
支持的最低客户端Windows Vista
和
支持的最低服务器Windows server 2008
因此,官方不能保证它们在旧操作系统上正常工作或提供全部功能。