Solved

Counting processes with the PDH

Posted on 1998-05-18
12
302 Views
Last Modified: 2013-12-03
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
Comment
Question by:shimon_crown
  • 4
  • 4
  • 3
  • +1
12 Comments
 
LVL 2

Expert Comment

by:tonp
ID: 1402567
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
 

Author Comment

by:shimon_crown
ID: 1402568
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
 
LVL 23

Expert Comment

by:chensu
ID: 1402569
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
 
LVL 2

Expert Comment

by:tonp
ID: 1402570
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
 
LVL 23

Expert Comment

by:chensu
ID: 1402571
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
 
LVL 2

Expert Comment

by:tonp
ID: 1402572
Ok, I see. Thanks for the info!
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:shimon_crown
ID: 1402573
See your own comment.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1402574
Have you tried what I suggested? Does it work?
0
 

Author Comment

by:shimon_crown
ID: 1402575
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
 
LVL 7

Expert Comment

by:BlackMan
ID: 1402576
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
 

Author Comment

by:shimon_crown
ID: 1402577
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
 
LVL 23

Accepted Solution

by:
chensu earned 300 total points
ID: 1402578
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Save copy of document in Word 4 76
What is UAC Virtualization in the Process (TASK) Manager? 4 1,248
Post a good COM tutorial 1 50
What .NET URL re-routing tool did I use? 2 38
This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now