[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 311
  • Last Modified:

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.
0
shimon_crown
Asked:
shimon_crown
  • 4
  • 4
  • 3
  • +1
1 Solution
 
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
NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

 
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

Featured Post

Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

  • 4
  • 4
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now