2015-11-27 1 views
-1

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.

+0

Windows XP est mort depuis longtemps, alors qui va réparer ça? –

+1

@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). –

+0

@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. –

Répondre

1

Tout comme la plupart des classes WMI Win32_OperatingSystem est déclaré avoir

client pris en charge minimum Windows Vista

et

serveur minimale prise en charge de Windows Server 2008

Ainsi, ils sont officiellement pas garanti pour fonctionner correctement ou fournir des fonctionnalités complètes sur l'ancien système d'exploitation.