There is the following C# code that uses WMI to get OsProductSuite value from Win32_OperatingSystem and the analogous wSuiteMask using WinApi function GetVersionEx :
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;
}
THE PROBLEM: On all OS after XP both WMI and GetVersionEx
report correct OSProductSuite
value. But on Windows XP the OSProductSuite
from WMI is null.
I originally considered that it is a problem in .NET wrappers for WMI, so I have shamelessly adapted the C++ code from Example: Getting WMI Data from the Local Computer to do the same thing (the changes are in the step 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.
}
But the variant type of the OSProductSuite
is VARENUM::VT_NULL (1)
, so it seems that the issue is with WMI itself. So, it is some XP issue with WMI, isn't it?
PS: While it is possible that there is some problem with XP distributives I used, or the issue stems from the fact that both machines are virtual (VmWare and SCVMM), it nonetheless seems rather doubtful.
Just as most of the WMI classes Win32_OperatingSystem is declared to have
Minimum supported client Windows Vista
and
Minimum supported server Windows Server 2008
Thus they are officially not guaranteed to work correctly or provide full capabilities on older OS.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.