none
Problem using WMI

    Question

  • HI all,

    I am quite new to C++. Recently, I am working on a project that requires me to get the processorId from computers. After a quick search on the internet, I found that WMI is the what I need. Subsequently, I get the following code from MSDN (http://msdn.microsoft.com/en-us/library/aa390423(VS.85).aspx):

    #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 --------------------------
    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------

    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 (e.g. 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;
    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 Name property
    hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
    wcout << " OS Name : " << vtProp.bstrVal << endl;
    VariantClear(&vtProp);
    }

    // Cleanup
    // ========

    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    pclsObj->Release();
    CoUninitialize();

    return 0; // Program successfully completed.

    }
    I added ->#include "stdafx.h"<- and tried to compile the code using Visual C++ 6.0 SP6.

    I get the following Error:
    fatal error C1083: Cannot open include file: 'Wbemidl.h': No such file or directory

    I search my computer and found that the header file is located at C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE.
    I then included the path C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE under tools->options->categories.
    I proceeded to compile it and get the following errors (shortened version):

    c:\program files\microsoft sdks\windows\v6.0a\include\wbemcli.h(1737) : error C2061: syntax error : identifier '__RPC__in'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemcli.h(1744) : error C2061: syntax error : identifier '__RPC__in_opt'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemcli.h(1748) : error C2061: syntax error : identifier '__RPC__deref_out_opt'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemcli.h(1751) : error C2061: syntax error : identifier '__RPC__in'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemcli.h(3071) : error C2061: syntax error : identifier '__RPC__in'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemcli.h(3723) : error C2061: syntax error : identifier '__RPC__in_opt'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemprov.h(273) : error C2146: syntax error : missing ';' before identifier 'LPWSTR'
    c:\program files\microsoft sdks\windows\v6.0a\include\wbemprov.h(273) : fatal error C1004: unexpected end of file found

    Again, I searched around the internet. From other people's question and answers, there is one suggesting that I should add
    #include <rpcsal.h>

    I added #include <rpcsal.h> and get the following error:
    fatal error C1083: Cannot open include file: 'sal.h': No such file or directory

    Then, I add the following diretory to the the categories: C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO 9.0\VC\INCLUDE
    Next, I get this error: error C2061: syntax error : identifier 'DWORD_PTR'
    I have no idea how to continue from here. I am afraid I made some mistake in the middle of some where.

    For your information, I installed the Visual Studio Express 2008 before installing Visual Studio 6.0.

    Is there anyone can help me?
    I would like to learn to use the WMI.
    I have read another tutorial/sample from the Code Project, but I got the same problem since it was also using #include <Wbemidl.h>.

    Hope you can help me.

    Thank you!


    Friday, August 29, 2008 2:20 AM

Answers

  • It can work, but you do need to take precautions. It is best to pass only POD (plain ole data) as parameters. Don't try to pass STL containers, for example, as this means the container functionality must be implemented the same in both client and DLL code (and they won't be if using different versions of the VC++ compiler). I would also use __stdcall as the calling conventions (although others might argue that this is unnecessary).

    Even better would be to convert the DLL to a COM DLL. However, you need to be knowledgeable about COM programming to do this. The reason is that COM DLL's can be called from just about any language that supports COM, which includes all the .NET languages, as well as Delphi, VB6 and many others (including VC6-compiled code).

    • Marked as answer by Yan-Fei Wei Tuesday, September 02, 2008 6:18 AM
    Tuesday, September 02, 2008 2:14 AM
  • Finally, the problem of using WMI is solved. Actually it's half solved.

    Building an unmanaged DLL in VS2008 and accessing using VS6 does not work for me(I believe it's due to my lack of knowledge in C++, DLL and COM).

    I decided to go back to VS 6 and give it another try.

    As Brian suggested, the problems that I faced earlier are due to that VS2008 SDK is not compatible with VS 6 SDK.

    Brian has also provided a link which pointed to me the resource to download the platform sdk from Microsoft website.

    However, I encountered some problem when I was trying to install it (as mentioned above).

    Then, I get download the Windows® Server 2003 SP1 Platform SDK Web Install from http://www.microsoft.com/downloads/details.aspx?familyid=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en

    I tried that once before I post this thread but has since uninstall it after a few tries. This time, I found that there is actually a function that called 'Register PSDK Directories with Visual Studio'.

    To my disappointment,  I get the following error when I am trying to build the app:
    1wbemuuid.lib(wbemcli_i.obj) : fatal error LNK1103: debugging information corrupt; recompile module<br>Error executing link.exe. 


    Then, I try to rebuild it again in release mode rather than debug mode and viola! I got no error message and the application run successfully. However, I don't understand why I got that error when I was trying to build it in debug mode. Thus I would say that the problem is half solved (despite it was mark as answered by other friendly readers). So far, I am quite happy with the result today. At least I can proceed from here rather than stuck half way. This is not possible without the help from readers here, especially Brian. Again, I would like to thank you all for the helps.

    Have a nice day :)
    • Marked as answer by lhkok Tuesday, September 02, 2008 7:46 AM
    • Marked as answer by lhkok Tuesday, September 02, 2008 7:46 AM
    • Marked as answer by lhkok Tuesday, September 02, 2008 7:46 AM
    Tuesday, September 02, 2008 7:45 AM

All replies

  • Try including windows.h file.
    Nave
    Friday, August 29, 2008 2:27 AM
  • Thank you Naveen for the prompt reply. I have added the windows.h as suggested. I get the same error.
    error C2061: syntax error : identifier 'DWORD_PTR'

    Sorry to ask another question in my own question. I have some doubt about the Wbemidl.h. Why is it not included in:
    C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
    C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
    C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE

    And which program is actually referring to C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE ?
    I have no idea since when I got that directory.


    Friday, August 29, 2008 2:34 AM
  • To let you better understand my situation, I would like to add some details.
    I have multiple version of visual studio(VS Express 2008, VS 6) installed in my PC with VS 6 being the latest install. I have installed the service pack 6 as well.
    In my Tools-> Option-> Directories, the default paths included are:
             C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
             C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
             C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE

    Due to the fatal error C1083: Cannot open include file: 'Wbemidl.h': No such file or directory error, I included C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE

    As I browse through some forum, there is one guy(http://www.tech-archive.net/Archive/Media/microsoft.public.windowsmedia.sdk/2007-02/msg00105.html) suggested to include rpcsal.h . Again, I have to include C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO 9.0\VC\INCLUDE since the header file is not available in those four directories which I have included earlier. However, the error persist as mentioned above in the first post.

    This morning, I changed the order of the path in Tools-> Option-> Directories from:
        C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
        C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
        C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE
        C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE
        C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO 9.0\VC\INCLUDE
    To:
        C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE
        C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
        C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
        C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE
        C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO 9.0\VC\INCLUDE
    Without changing any line of the codes, I get a different error messages which are:

    c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(3417) : warning C4035: 'ReadPMC' : no return value
    c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(3447) : warning C4035: 'ReadTimeStampCounter' : no return value
    c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(4340) : warning C4068: unknown pragma
    c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(4341) : warning C4068: unknown pragma
    c:\program files\microsoft visual studio\vc98\include\comdef.h(695) : error C2065: 'IAsyncSetup' : undeclared identifier
    c:\program files\microsoft visual studio\vc98\include\comdef.h(710) : error C2065: 'IClassAccess' : undeclared identifier
    c:\program files\microsoft visual studio\vc98\include\comdef.h(712) : error C2065: 'IClassAdmin' : undeclared identifier
    c:\program files\microsoft visual studio\vc98\include\comdef.h(715) : error C2065: 'IClassRefresh' : undeclared identifier
    c:\program files\microsoft visual studio\vc98\include\comdef.h(750) : error C2065: 'IEnumClass' : undeclared identifier
    c:\program files\microsoft visual studio\vc98\include\comdef.h(762) : error C2065: 'IEnumPackage' : undeclared identifier
    c:\program files\microsoft visual studio\vc98\include\comdef.h(1078) : error C2065: 'IXMLElementNotificationSink' : undeclared identifier
    Error executing cl.exe.

    Is this a problem of my installation?
    Or there are multiple version of header files with the same file names?
    I don't understand why the header files is scattering in different places. Also, why rpcsal.h is not available in VC98\include folder nor is it available in C:\PROGRAM FILES\MICROSOFT SDKS\WINDOWS\V6.0A\INCLUDE?
    Did I included any functions all files which is meant for .NET?

    I am so confused. Please advice.

    Monday, September 01, 2008 3:10 AM
  • The Microsoft SDK that shipped with VS 2008 is not compatible with VC6. I believe that last SDK that shipped that was compatible with VC6 is from Feb 2003 of the MSDN Library.

    I believe you can still download it from here.

    Monday, September 01, 2008 3:34 AM
  • Thanks for your kind reply.

    The link you provided is to download the 'Windows Server 2003 PSDK Full Download with Local Install'. I am using Windows XP Home, do I really need that? Anyhow, after I first encountered the problem, I have installed the "PSDK -x86.exe" from the MSDN. Is the file the same as those in the links you provided.

    Since you mentioned that the VC6 sdk and vc2008 is not compatible, will uninstalling both my vs20008 and vs6 and then reinstall my VC6 help?
    Monday, September 01, 2008 3:49 AM
  • The naming of the SDK's are confusing, so let me clarify.

    Because you are trying to create a project that uses WMI, you need the wbemidl.h header file. This is part of the Windows Management Instrumentation SDK. The WMI SDK is actually a subset of the Microsoft SDK. The Microsoft SDK ships as part of Visual Studio 2008, and you can see the header files that belong to the Microsoft SDK in the \Program Files\Microsoft SDKs\Windows\v6.0a\include folder.

    The Microsoft SDK used to be called the Platform SDK. The Platform SDK did not ship with VS6; you had to download it separately from Microsoft. The last Platform SDK that was compatible with VS6 shipped in Feb 2003. You can download that Platform SDK from the link I posted. Ignore that fact that it looks like it was targeting Microsoft Windows 2003 Server. Later versions of the Platform SDK and Microsoft SDK do not work with VC6.

    Monday, September 01, 2008 4:57 AM
  • Thank you for the clarification.

    I will try the solution.

    By the way, that means it's okay to keep the both version of VS, isn't it?

    Monday, September 01, 2008 5:03 AM


  • I have downloaded the SDK packages and extract it into a temp folder as instructed in the web site provided. Then I double click the setup.exe file to launch the installation program. It then prompt me to use IE 5.0 and above (I was using firefox as my default browser). It was very dissapoiting that the installer 'force' me to set my browser default to IE.  I have no issue with Microsoft but the firefox 3.0 is a better browser for me :) . Anyway, since I was desperate to solve the issue, I switch my default browser to IE. I then run the setup.exe again. Unfortunately, an error message pop up as below:

    IEXPLORE.EXE - Application Error

    The instruction at "0x062e0068" referenced memory at "0x062e0068". The memory could not be "written".

    Click on OK to terminate the program
    Click on CANCEL to debug the program

    I am using IE 8 beta 2. Is that a problem with my IE version? Or is there any way to install the SDK without using a browser?


    Please help.


    Monday, September 01, 2008 7:17 AM
  • Sorry to reply to my own threads. I would like to add some details.

    The instruction number 6 at the SDK download site stated that :
    6.Run Setup.exe to install the Platform SDK using the SDK Update interface.

    Then, there website also noted that:
    Note: To ensure that you can upgrade later using SDK Update, do not run the Windows Installer files directly.

    Does anyone know what it means by 'do not run the Windows Installer files directly'?


    Does anyone has the similar experience when trying to develop an WMI application using VC 6?
    I am using standard software without any tweaks. From the WMI website of MSDN, this problem was never mentioned. Is this a rare case?
    I assume there must be quite a lot of developers out there developing WMI app using VC 6 right? I am afraid I am not tackling the problem at the root. This problem has bugging me for a couple of days and I was stuck here and not able to proceed. I am willing to take any drastic methods ( reinstalling the IDE etc.) to overcome this issue.

    I really appreciate your help.
    Looking forward for you replies soon. Thanks for those who have viewed the topics and special thanks to those who have replied.
    Monday, September 01, 2008 7:37 AM
  • It means there are probably *.msi files that are packed in the cab files, and you shouldn't run them directly. Use setup.exe instead.

    May I remind you, you are using VC6 which is more than 10 years old and is obsolete. You have to install an obsolete version of the Platform SDK to create an obsolete environment in order to compile this code. I'm not sure what other problems lie around the next corner, but I suspect it will be possible to get this to work.

    This would not be my strategy. I would use Visual Studio 2008 instead. (I don't know if the Express Edition would suffice. Standard edition will work.)
    Monday, September 01, 2008 5:33 PM
  • The only reason I would use VC6 to develop a DLL is that our client uses VC 6 to develop their app.
    I have actually posted another related question at here:
    http://forums.msdn.microsoft.com/en-US/vcgeneral/thread/c7f4f7dd-11f6-4502-a709-fc4266794a5d

    If I were to develop unmanaged DLL using VS 2008, can my client who uses VC 6 access the DLL?
    They will not involve in the development of the DLL but merely using it to access certain lower level functions in their app.
    Is there any extra precaution (or even will this work?) that I have to take note if I were to follow this path?


    Tuesday, September 02, 2008 1:38 AM
  • It can work, but you do need to take precautions. It is best to pass only POD (plain ole data) as parameters. Don't try to pass STL containers, for example, as this means the container functionality must be implemented the same in both client and DLL code (and they won't be if using different versions of the VC++ compiler). I would also use __stdcall as the calling conventions (although others might argue that this is unnecessary).

    Even better would be to convert the DLL to a COM DLL. However, you need to be knowledgeable about COM programming to do this. The reason is that COM DLL's can be called from just about any language that supports COM, which includes all the .NET languages, as well as Delphi, VB6 and many others (including VC6-compiled code).

    • Marked as answer by Yan-Fei Wei Tuesday, September 02, 2008 6:18 AM
    Tuesday, September 02, 2008 2:14 AM
  • Thanks. I am going to try it out.
    I really appreciate your answer.
    Tuesday, September 02, 2008 2:18 AM
  • Finally, the problem of using WMI is solved. Actually it's half solved.

    Building an unmanaged DLL in VS2008 and accessing using VS6 does not work for me(I believe it's due to my lack of knowledge in C++, DLL and COM).

    I decided to go back to VS 6 and give it another try.

    As Brian suggested, the problems that I faced earlier are due to that VS2008 SDK is not compatible with VS 6 SDK.

    Brian has also provided a link which pointed to me the resource to download the platform sdk from Microsoft website.

    However, I encountered some problem when I was trying to install it (as mentioned above).

    Then, I get download the Windows® Server 2003 SP1 Platform SDK Web Install from http://www.microsoft.com/downloads/details.aspx?familyid=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en

    I tried that once before I post this thread but has since uninstall it after a few tries. This time, I found that there is actually a function that called 'Register PSDK Directories with Visual Studio'.

    To my disappointment,  I get the following error when I am trying to build the app:
    1wbemuuid.lib(wbemcli_i.obj) : fatal error LNK1103: debugging information corrupt; recompile module<br>Error executing link.exe. 


    Then, I try to rebuild it again in release mode rather than debug mode and viola! I got no error message and the application run successfully. However, I don't understand why I got that error when I was trying to build it in debug mode. Thus I would say that the problem is half solved (despite it was mark as answered by other friendly readers). So far, I am quite happy with the result today. At least I can proceed from here rather than stuck half way. This is not possible without the help from readers here, especially Brian. Again, I would like to thank you all for the helps.

    Have a nice day :)
    • Marked as answer by lhkok Tuesday, September 02, 2008 7:46 AM
    • Marked as answer by lhkok Tuesday, September 02, 2008 7:46 AM
    • Marked as answer by lhkok Tuesday, September 02, 2008 7:46 AM
    Tuesday, September 02, 2008 7:45 AM