Why doesn't PDH work?

Hello,

I've been trying to develop an application that reads the CPU load from the computer and the free RAM memory available. To do so, I was primarily thinking about using the PDH interface, since we are building to Windows Server 2003 and Windows XP, both of which already come with the PDH.dll. I downloaded the platform SDK from Microsoft's site, and I am using Visual Studio 2005.

My dilemma is, every time I try to compile the source code, it gives me several errors, even with example codes taken from Microsoft's site. It gives me several unindentified objects in _main (it cannot understand/localize the commands, datatypes and so on). I don't understand why. I tried copying the pdh.h and pdh.lib to the main include & lib folders of Visual Studio, I even tried other compilers - it just doesn't work. It gives me the same errors. I am sure I have the PDH.dll that came with Windows XP.

Does anyone know why it is so



Answer this question

Why doesn't PDH work?

  • sjsn

    You're being a bit vague in your problem description. Please give us the code (in as few lines as possible) you're trying along with the exact error you are getting.
  • Abongs

    It works! It works! I'll graduate this year!
    It only gives me this error when I try to debug:

    'attempt.exe': Loaded 'D:\TCC\PDH\attempt\debug\attempt.exe', Binary was not built with debug information.

    Many thanks!

  • Indigo Cowboy

    Here they are:

    Project Properties, C/C++, General, Debug Information Format = Program Database for Edit & Continue (/ZI)

    Project Properties, Linker, Debugging, Generate Debug Info = Yes (/Debug)


  • moondaddy

    That looks right.

    If an API expects LPCSTR, give it const char*. If it expects LPCWSTR, you give it const wchar_t*. If it expects LPCTSTR, meaning the type depends on whether _UNICODE is defined, you give it const TCHAR*. In Jonathan's answer, he was assuming that the API was using LPCTSTR.

    The literal string "hello" is const char*. The literal string L"world" is const wchar_t*. The literal strings _T("hello") and TEXT("hello") both mean the same thing and are const TCHAR* (i.e. they either evaluate to "hello" or L"hello" depending on _UNICODE).

    Hope this clear things up.

    Brian


  • Perry Choy

    Thank you very much guys, you've helped me a lot. I'm new to Visual Studio and C++ programming, hence my (easy) confusion :)
  • aragon127

    Somehow you disabled debug info. You want to turn on debugging info in the compiler settings (/ZI or /Zi flag) as well as during the link step (/debug flag). I don't have VS in front of me, so I can't give you the exact location.
  • Tarey Wolf

    I tried compiling this exect code in my visual C++ express edition and gets the following error.

    Any idea
    pdh.h changed since

    ------ Build started: Project: test123, Configuration: Debug Win32 ------
    Compiling...
    test 123.cpp
    d:\profiles\user\my documents\visual studio 2005\projects\test123\test123\test 123.cpp(16) : error C2440: 'initializing' : cannot convert from 'const wchar_t [32]' to 'CHAR [45]'
    There is no context in which this conversion is possible
    d:\profiles\user\my documents\visual studio 2005\projects\test123\test123\test 123.cpp(24) : error C2664: 'PdhAddCounterW' : cannot convert parameter 2 from 'CHAR [45]' to 'LPCWSTR'
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    d:\profiles\userl\my documents\visual studio 2005\projects\test123\test123\test 123.cpp(29) : error C2664: 'PdhOpenLogW' : cannot convert parameter 1 from 'char [24]' to 'LPCWSTR'
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    Build log was saved at "file://d:\Profiles\user\My Documents\Visual Studio 2005\Projects\test123\test123\Debug\BuildLog.htm"
    test123 - 3 error(s), 0 warning(s)
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

  • omrivm

    Erm not sure what that means exectly but I found from pdh.h that PdhAddCounter expects LPCWSTR instead of CHAR... so modified alittle bit the code to the one below.

    Any comments

    btw I'm very new to VC++, so be gentle please.

    -ed

  • Rraj

    Thanks. Looks like you're almost there.

    You need to add the import library that contains the _Pdhxxx functions so that the linker can locate these functions. Is it pdh.lib If so, add this to Project Properties, Linker, Input, Additional Dependencies. Be sure to add it for both debug and release configurations.


  • Hybrid Bray der Burrito

    You want to go to Project Properties -> Configuration Properties -> C/C++ -> General and in the "Debug Information Format" make sure you choose either "Program Database (/Zi)" or "Program Database for Edit & Continue (/ZI)". Selecting one of these two options should ensure that the correct options are sent to both the compiler and the linker.



  • penninha

    You are compiling for Unicode but you are using narrow string constants. Try _T("Hello") instead of just "Hello".

  • Kiranvukkadala

    Ah, yes; well, this is the code I am trying to compile:

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    #include <pdh.h>
    #include <pdhmsg.h>

    int __cdecl _tmain (void)
    { HLOG phLog;
    PDH_STATUS pdhStatus;
    HCOUNTER phCounter;
    DWORD count;
    char szFileName[24];
    WORD dwUserData = 0;
    HQUERY hQuery = NULL;
    DWORD logType = PDH_LOG_TYPE_CSV;
    CHAR szCounterPath[45] = TEXT("\\Process(calc)\\% Processor Time");
    strcpy( szFileName, "QuickMonitor.log");

    // Open a query.
    (pdhStatus = PdhOpenQuery( NULL, 0, &hQuery));


    // Add a counter.
    pdhStatus = PdhAddCounter( hQuery, szCounterPath,dwUserData,&phCounter) ;


    // Open the log file for write access.
    pdhStatus = PdhOpenLog (szFileName, PDH_LOG_WRITE_ACCESS | PDH_LOG_CREATE_ALWAYS ,
    &logType, hQuery, 0, NULL, &phLog);

    // Capture 10 samples and write them to the log.
    for (count = 0; count <= 10; count++) {
    pdhStatus = PdhUpdateLog (phLog, TEXT("Some Text."));
    Sleep(1000); // Sleep for 1 seconds between samples
    }
    // Close the log and the Query
    pdhStatus = PdhCloseLog (phLog, PDH_FLAGS_CLOSE_QUERY);

    return 0;
    }

    I took that source code from an IBM tutorial I found in the Web. And these are the errors it gives me:

    ------ Build started: Project: attempt, Configuration: Debug Win32 ------
    Linking...
    main.obj : error LNK2019: unresolved external symbol _PdhCloseLog@8 referenced in function _main
    main.obj : error LNK2019: unresolved external symbol _PdhUpdateLogA@8 referenced in function _main
    main.obj : error LNK2019: unresolved external symbol _PdhOpenLogA@28 referenced in function _main
    main.obj : error LNK2019: unresolved external symbol _PdhAddCounterA@16 referenced in function _main
    main.obj : error LNK2019: unresolved external symbol _PdhOpenQueryA@12 referenced in function _main
    D:\TCC\PDH\attempt\Debug\attempt.exe : fatal error LNK1120: 5 unresolved externals
    Build log was saved at "file://d:\TCC\PDH\attempt\attempt\Debug\BuildLog.htm"
    attempt - 6 error(s), 0 warning(s)
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


  • Why doesn't PDH work?