Il y a le code C# suivant qui utilise WMI pour obtenir la valeur OSProductSuite de Win32_OperatingSystem et wSuiteMask analogue en utilisant WinApi function GetVersionEx:WMI Win32_OperatingSystem OSProductSuite donne une valeur incorrecte sur Windows XP
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;
}
PROBLÈME: Sur tous les OS après XP à la fois WMI et GetVersionEx
rapport correct OSProductSuite
valeur. Mais sur Windows XP, le OSProductSuite
de WMI est nul.
Au départ, je considère qu'il est un problème dans des emballages .NET pour WMI, donc je suis sans vergogne adapté le code C++ de Example: Getting WMI Data from the Local Computer faire la même chose (les changements sont à l'étape 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.
}
Mais le type de variante de OSProductSuite
est VARENUM::VT_NULL (1)
, il semble donc que le problème est avec WMI lui-même. Donc, c'est un problème d'XP avec WMI, n'est-ce pas?
P.S .: Il est possible qu'il y ait un problème avec XP distributives j'ai utilisé, ou la question découle du fait que les deux machines sont virtuelles (VmWare et SCVMM), il semble néanmoins assez douteux.
Windows XP est mort depuis longtemps, alors qui va réparer ça? –
@LexLi Je comprends, mais il a encore [11% de part de marché] (https://www.netmarketshare.com/operating-system-market-share.aspx?qprid=10&qpcustomd=0). Je veux juste être sûr que c'est vraiment un défaut et non un problème de configuration (distributive). –
@LexLi, non, ce n'est pas mort. Certaines personnes, en particulier l'ancienne génération, ont eu des difficultés à apprendre à utiliser un ordinateur et leur courbe d'apprentissage s'est avérée être active alors que Windows XP était encore une nouveauté. Maintenant, vous ne serez pas vraiment capable de convaincre ceux qui se souviennent très intensément de la douleur d'apprendre à utiliser un ordinateur pour apprendre un nouveau système d'exploitation parce que vous prétendez que celui qu'ils utilisent est mort. Ils verront que les programmes qu'ils utilisent fonctionnent toujours et ignoreront vos arguments. –