Click to See Complete Forum and Search --> : Trying to Use pdh.h


kuhns_m
March 4th, 2002, 03:08 PM
I am trying to incorporate pdh.h into an ATL project. Here is an example of the code I am using

// reader.cpp : Implementation of Creader



#include "stdafx.h"
#include "Perfreader.h"
#include "reader.h"

#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#include <tchar.h>
#include <pdhmsg.h>
#include <pdh.h>

/////////////////////////////////////////////////////////////////////////////
// Creader


// Not the best of programming practice but
// I've had better luck with static buffers
// than getting buffer length information
// from PDH functions. Often times a function,
// when passing NULL pointer to request
// the buffer size it would return the
// wrong amount

#define MACHINE_LIST_SIZE 1024
#define OBJECT_LIST_SIZE 4096
#define COUNTER_LIST_SIZE 8192
#define INSTANCE_LIST_SIZE 8192

#define PATH_BUFF_SIZE 256
#define TITLE_SIZE 512


// command codes of get_cmd_args
/*
#define GCA_PARSE_ERROR 0
#define GCA_ENUM 1
#define GCA_DUMP 2

// prototypes of functions implemented in this source

void enum_perflog_items(
LPCTSTR lpszLogFile
);

void perf_log_dump(
LPTSTR lpszLogFile,
LPTSTR lpszObj,
LPTSTR lpszCntr,
LPTSTR lpszInst);

void load_stack(DWORD dwVal);

void print_usage(TCHAR *szAppname);

void print_copyright(void);

DWORD get_cmd_args(
int argc,
TCHAR **argv,
LPTSTR *lppszLogFile,
LPTSTR *lppszObj,
LPTSTR *lppszCntr,
LPTSTR *lppszInst
);

void print_pdh_error(
LPTSTR lpszFuncName,
PDH_STATUS pdhStatus
);
*/
void enum_perflog_items(
LPCTSTR lpszLogFile
)
{
PDH_STATUS pdhStatus = 0;
HLOG hLog = NULL;
DWORD dwCharsNeeded = 0;
TCHAR mszMachines[MACHINE_LIST_SIZE];
TCHAR mszObjects[OBJECT_LIST_SIZE];
TCHAR mszCounters[COUNTER_LIST_SIZE];
TCHAR mszInstances[INSTANCE_LIST_SIZE];
TCHAR szTitle[TITLE_SIZE];
PDH_TIME_INFO pdhTimeInfo;
SYSTEMTIME stStart, stEnd;
DWORD dwBufferSize = 0;
DWORD dwNumEntries = 0;
DWORD dwItemIndex = 0;
LPTSTR lptrObj = NULL;
LPTSTR lpszMachine = NULL;

memset(mszMachines, 0, MACHINE_LIST_SIZE * sizeof(TCHAR));
memset(mszObjects, 0, OBJECT_LIST_SIZE * sizeof(TCHAR));
memset(mszCounters, 0, COUNTER_LIST_SIZE * sizeof(TCHAR));
memset(mszInstances, 0, INSTANCE_LIST_SIZE * sizeof(TCHAR));
memset(szTitle, 0, TITLE_SIZE * sizeof(TCHAR));
memset(&pdhTimeInfo, 0, sizeof(dwBufferSize));


// enumerate machines in the log file
dwCharsNeeded = MACHINE_LIST_SIZE;
pdhStatus = PdhEnumMachines(lpszLogFile, mszMachines, &dwCharsNeeded);
if (IsErrorSeverity(pdhStatus))
{
//print_pdh_error(TEXT("PdhEnumObjects"), pdhStatus);
return;
}

// output multistring enumeration
lpszMachine = mszMachines;
//_tprintf(TEXT("%s contains info from the following machine names\n"),
// lpszLogFile);
while (*lpszMachine)
{
// _tprintf(TEXT("%s\n"), lpszMachine);
lpszMachine = lpszMachine + lstrlen(lpszMachine) + 1; // next string
}
//_tprintf(TEXT("\n"));


// typically you would enumerate objects/counters for each
// machine but in this example I only enumerate the such for
// the first machine.
lpszMachine = mszMachines;


dwCharsNeeded = OBJECT_LIST_SIZE;
pdhStatus = PdhEnumObjects(
lpszLogFile,
lpszMachine,
mszObjects,
&dwCharsNeeded,
PERF_DETAIL_WIZARD,
TRUE);

if (IsErrorSeverity(pdhStatus))
{
// print_pdh_error(TEXT("PdhEnumObjects"), pdhStatus);
return;
}

// Here's a funky thing to note.
// If lpszLogFile refers to a perfmon type log, and
// if the buffer is not large enough for object titles,
// this function will succeed in return object indexes
// This is also true for PdhEnumObjectItems.

// iterate through objects and get items for each
lptrObj = mszObjects;
while (*lptrObj)
{
DWORD dwCntrCharsNeeded;
DWORD dwInstCharsNeeded;

LPTSTR lptrItem, lptrItem2;
LPTSTR counter;

dwCntrCharsNeeded = COUNTER_LIST_SIZE;
dwInstCharsNeeded = INSTANCE_LIST_SIZE;


pdhStatus = PdhEnumObjectItems(
lpszLogFile,
lpszMachine,
lptrObj,
mszCounters,
&dwCntrCharsNeeded,
mszInstances,
&dwInstCharsNeeded,
PERF_DETAIL_WIZARD,
0);

if (IsErrorSeverity(pdhStatus))
{
// print_pdh_error(TEXT("PdhEnumObjectItems"), pdhStatus);
break;
}

//_tprintf(TEXT("Items for %s\n================\n"), lptrObj);


// enumerate counter items
//_tprintf(TEXT("Counters\n"));

lptrItem = mszCounters;
while (*lptrItem)
{
// _tprintf(TEXT("\t%s\n"), lptrItem);
counter = lptrItem;
// not all objects have instances
// dwInstCharsNeeded will be zero if no instances
if (dwInstCharsNeeded)
{
lptrItem2 = mszInstances;
// _tprintf(TEXT("Instances\n"));

while (*lptrItem2)
{
// _tprintf(TEXT("\t%s\n"), lptrItem2);
//call dump log with timing info
// perf_log_dump(lpszLogFile, lptrObj, counter, lptrItem2);
lptrItem2 += lstrlen(lptrItem2) + 1; // get next string
}

//_tprintf(TEXT("\n\n"));
}
else {
//perf_log_dump(lpszLogFile, lptrObj, counter, NULL);
}

lptrItem += lstrlen(lptrItem) + 1; // get next string
}

//_tprintf(TEXT("\n"));

lptrObj += lstrlen(lptrObj) + 1; // get next object
} // while (*lptrObj)



// todo: add code to display the data query range
dwBufferSize = sizeof(PDH_TIME_INFO);
pdhStatus = PdhGetDataSourceTimeRange(lpszLogFile, &dwNumEntries,
&pdhTimeInfo, &dwBufferSize);
if (IsErrorSeverity(pdhStatus))
{
//print_pdh_error(TEXT("PdhGetDataSourceTimeRange"), pdhStatus);
return;
}

FileTimeToSystemTime((LPFILETIME)&(pdhTimeInfo.StartTime), &stStart);
FileTimeToSystemTime((LPFILETIME)&(pdhTimeInfo.EndTime), &stEnd);

//_tprintf(TEXT("Time range of %s\n"), lpszLogFile);
//_tprintf(TEXT("Start Time: %2d/%2d/%4d %2d:%2d:%2d\n"),
// stStart.wMonth, stStart.wDay, stStart.wYear,
// stStart.wHour, stStart.wMinute, stStart.wSecond);
//_tprintf(TEXT(" End Time: %2d/%2d/%4d %2d:%2d:%2d\n"),
// stEnd.wMonth, stEnd.wDay, stEnd.wYear,
// stEnd.wHour, stEnd.wMinute, stEnd.wSecond);
//_tprintf(TEXT("Contains %d data samplings\n"), pdhTimeInfo.SampleCount);


}


STDMETHODIMP Creader::getPerfmonData(BSTR *logfile, BSTR *startTime, BSTR *endTime, BSTR *connStr)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())



return S_OK;
}



When I compile this as a console project it works fine. When I put this code into a MFC or ATL project I get the following errors

With the #define UNICODE & #define _UNICODE statements:
D:\Source\perfreader\reader.cpp(107) : error C2664: 'PdhEnumMachinesW' : cannot convert parameter 1 from 'const char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
D:\Source\perfreader\reader.cpp(139) : error C2664: 'PdhEnumObjectsW' : cannot convert parameter 1 from 'const char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
D:\Source\perfreader\reader.cpp(176) : error C2664: 'PdhEnumObjectItemsW' : cannot convert parameter 1 from 'const char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
D:\Source\perfreader\reader.cpp(229) : error C2664: 'PdhGetDataSourceTimeRangeW' : cannot convert parameter 1 from 'const char *' to 'const unsigned short *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Error executing cl.exe.

without the #define UNICODE & #define _UNICODE statements:
reader.obj : error LNK2001: unresolved external symbol _PdhGetDataSourceTimeRangeA@16
reader.obj : error LNK2001: unresolved external symbol _PdhEnumObjectItemsA@36
reader.obj : error LNK2001: unresolved external symbol _PdhEnumObjectsA@24
reader.obj : error LNK2001: unresolved external symbol _PdhEnumMachinesA@12
Debug/perfreader.dll : fatal error LNK1120: 4 unresolved externals

My system information is Windows 2000 Advanced Server
Thank you in advance