Counting processes with the PDH

My program is supposed to count the number & names of processing currently running on a windows NT 4 workstation.

I am using PdhEnumObjectItems to get this information.
For some reason the information returned is only correct for the first call to this function. Subsequent calls always return the same number of processes even if the number of processes has changed. Any ideas.
shimon_crownAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

tonpCommented:
I would suggest to take a different route. The PSAPI interface is more suited to your task (with functions like EnumProcess and EnumProcessModules). A (very) complete description of how to handle your task can be found in Microsoft's knowledgebase article Q175030 (www.microsft.com).
0
shimon_crownAuthor Commented:
I am aware of this possibility but for this particular project I am using the PDH for getting other information related to system performance. This cannot be obtained from the PSAPI so it would be much neater to avoid using it altogether.
0
chensuCommented:
It seems to be a bug of Win32. You may try creating a thread to call PdhEnumObjectItems each time you need the information. Hope it will get the latest information.
0
Exploring SharePoint 2016

Explore SharePoint 2016, the web-based, collaborative platform that integrates with Microsoft Office to provide intranets, secure document management, and collaboration so you can develop your online and offline capabilities.

tonpCommented:
I just tried out a simple program, listing processes with the pdh functions (copied source directly from MSDN). Seems to work fine, it correctly lists new processes. Copy the code below and compile it. Now, run it (in a command prompt). Next start some process (e.g. notepad) and run the test app again. It will correctly show the new notepad process (at least, this is what I see on my NT 4.0 sp3 machine).

---- pdh.cpp ----
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE  1
#endif
#define tmain     wmain
#else
#define tmain     main
#endif

// This program only needs the essential windows header files.
#define WIN32_LEAN_AND_MEAN 1

#include <windows.h>
#include <winperf.h>
#include <malloc.h>
#include <stdio.h>
#include <tchar.h>
#include <pdh.h>

int tmain ()
{
    PDH_STATUS  pdhStatus               = ERROR_SUCCESS;
    LPTSTR      szCounterListBuffer     = NULL;
    DWORD       dwCounterListSize       = 0;
    LPTSTR      szInstanceListBuffer    = NULL;
    DWORD       dwInstanceListSize      = 0;
    LPTSTR      szThisInstance          = NULL;


// Determine the required buffer size for the data.

    pdhStatus = PdhEnumObjectItems (
        NULL,                   // reserved
        NULL,                   // local machine
        TEXT("Process"),        // object to enumerate
        szCounterListBuffer,    // pass in NULL buffers
        &dwCounterListSize,     // an 0 length to get
        szInstanceListBuffer,   // required size
        &dwInstanceListSize,    // of the buffers in chars
        PERF_DETAIL_WIZARD,     // counter detail level
        0);

    if (pdhStatus == ERROR_SUCCESS)
    {
    // Allocate the buffers and try the call again.
        szCounterListBuffer = (LPTSTR)malloc (
            (dwCounterListSize * sizeof (TCHAR)));
        szInstanceListBuffer = (LPTSTR)malloc (
            (dwInstanceListSize * sizeof (TCHAR)));
        if ((szCounterListBuffer != NULL) &&
            (szInstanceListBuffer != NULL))
        {
            pdhStatus = PdhEnumObjectItems (
                NULL,   // reserved
                NULL,   // local machine
                TEXT("Process"), // object to enumerate
                szCounterListBuffer,    // pass in NULL buffers
                &dwCounterListSize,     // an 0 length to get
                szInstanceListBuffer,   // required size
                &dwInstanceListSize,    // of the buffers in chars
                PERF_DETAIL_WIZARD,     // counter detail level
                0);    
            if (pdhStatus == ERROR_SUCCESS)
            {
                _tprintf (TEXT("\nRunning Processes:"));
            // Walk the return instance list.
                for (szThisInstance = szInstanceListBuffer;
                     *szThisInstance != 0;
                     szThisInstance += lstrlen(szThisInstance) + 1)
                {
                     _tprintf (TEXT("\n  %s"), szThisInstance);
                }
            }
        }
        else
        {
            _tprintf (TEXT("\nPROCLIST: unable to allocate buffers"));
        }

        if (szCounterListBuffer != NULL)
            free (szCounterListBuffer);

        if (szInstanceListBuffer != NULL)
            free (szInstanceListBuffer);
    }
    else
    {
        _tprintf(TEXT("\nUnable to determine required buffer size."));
    }
    return 0;
}

0
chensuCommented:
tonp,

You misunderstand the problem. Yes, if you quit the program and restart it again, it will list the lastest information. That is why I suggest creating a thread. But, what shimon_crown is talking about is during the program session. You may make a loop to call PdhEnumObjectItems. When it is running, open some new applications to see what happens.
0
tonpCommented:
Ok, I see. Thanks for the info!
0
shimon_crownAuthor Commented:
See your own comment.
0
chensuCommented:
Have you tried what I suggested? Does it work?
0
shimon_crownAuthor Commented:
Not yet as I have been in a course. While I don't think this is a practical suggestion if only because the project demands a very stable NT without starting and stopping threads all the time it is worth looking into to see if it can shed more light on the bug.
Practically  I shall probably revert to using PSAPI as suggested by tonp.
0
BlackManCommented:
Are you sure that your CounterListBuffer and InstanceListBuffer are large enough for holding all the informations? If you allocate them on the first call based on the required size, there will be no room for new processes. I think the best solution is in each call to yor procedure to query about the size (send CounterListSize=0), allocate the buffer, get the objects and deallocate the buffer. This way you are sure that the buffer is always large enough.
0
shimon_crownAuthor Commented:
Sorry it still doesn't work. I tried chensu's method and it works so if he wants to resubmit the answer the points are his.
0
chensuCommented:
It seems to be a bug of Win32. You may try creating a thread to call PdhEnumObjectItems each time you need the information.

Thank you.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.