deck16
asked on
Harddrive Usage?
Is it possible to get a usage statistic for the harddrive? I'm looking for somthing similar to the CPU usage statistic that can be found in the registry. This wouldn't have to be a perfect statistic, but just an approximate indicator of how hard the harddrive is working. For example 0% when it's idle. And 100% when it's spinning at it's full speed and conducting intensive access. If that's not possible, is there a way to just detect if harddrive activity is occuring at a certain point in time?
winnt and family have this in the performance monitor, it will graph it for you and give numbers, but its not something you can read in a program, just for humans to read and see what the holdup is...
ASKER
umm, if the performance monitor can get the stats i should be able to do the same thing in my program.
ASKER
does anybody have any ideas?
if you can't find a windows way, you can go low level. Trap the interrupt(s?) that writes to the hd and do something (take stats) when it trips. The hd write is probably a bios interrupt, not sure, haven't looked at this since 386's were common...
windows may have a way you can use or it can cheat (the os knows when it is writing, even if it does not have a method to look at this that can be used)
windows may have a way you can use or it can cheat (the os knows when it is writing, even if it does not have a method to look at this that can be used)
probably u can do it thru StartTrace() function. fill out the EVENT_TRACE_PROPERTIES structure and enable the EVENT_TRACE_FLAG_DISK_IO flag.
see article "Starting an Event Tracing Session" on MSDN.
this may help u
good luck
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
> performance monitor, it will graph it for you and give numbers, but
its not something you can read in a program, just for humans to read and see what the holdup is
You can read the performance monitor data in a C++ program. Here is code to read the CPU Usage:
// CpuUsage.h: interface for the CCpuUsage class.
//
////////////////////////// ////////// ////////// ////////// ////////// ////
#if !defined(AFX_CPUUSAGE_H__6 0CF4F03_9F 01_41E8_A9 FB_51F065D 5F3C2__INC LUDED_)
#define AFX_CPUUSAGE_H__60CF4F03_9 F01_41E8_A 9FB_51F065 D5F3C2__IN CLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define MAX_RAW_VALUES 20
const char szCounterName[] = "\\Processor(_Total)\\% Processor Time";
typedef struct _tag_PDHCounterStruct {
HCOUNTER hCounter; // Handle to the counter - given to use by PDH Library
int nNextIndex; // element to get the next raw value
int nOldestIndex; // element containing the oldes raw value
int nRawCount; // number of elements containing raw values
PDH_RAW_COUNTER a_RawValue[MAX_RAW_VALUES] ; // Ring buffer to contain raw values
} PDHCOUNTERSTRUCT, *PPDHCOUNTERSTRUCT;
class CCpuUsage
{
public:
CCpuUsage();
virtual ~CCpuUsage();
BOOL Init();
int GetUsage();
protected:
PPDHCOUNTERSTRUCT m_pCounterStruct;
HQUERY m_hQuery;
};
#endif // !defined(AFX_CPUUSAGE_H__6 0CF4F03_9F 01_41E8_A9 FB_51F065D 5F3C2__INC LUDED_)
// CpuUsage.cpp: implementation of the CCpuUsage class.
//
////////////////////////// ////////// ////////// ////////// ////////// ////
#include "stdafx.h"
#include "CpuUsage.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
////////////////////////// ////////// ////////// ////////// ////////// ////
// Construction/Destruction
////////////////////////// ////////// ////////// ////////// ////////// ////
CCpuUsage::CCpuUsage()
{
m_hQuery = NULL;
m_pCounterStruct = NULL;
}
CCpuUsage::~CCpuUsage()
{
PdhCloseQuery(m_hQuery);
delete m_pCounterStruct;
}
BOOL CCpuUsage::Init()
{
if (ERROR_SUCCESS != PdhOpenQuery(NULL, 1, &m_hQuery))
return FALSE;
m_pCounterStruct = (PPDHCOUNTERSTRUCT) new PDHCOUNTERSTRUCT;
PDH_STATUS pdh_status = PdhAddCounter(m_hQuery, szCounterName, (DWORD) m_pCounterStruct, &(m_pCounterStruct->hCount er));
if (ERROR_SUCCESS != pdh_status)
{
return FALSE;
}
return TRUE;
}
int CCpuUsage::GetUsage()
{
PDH_FMT_COUNTERVALUE pdhFormattedValue;
PdhCollectQueryData(m_hQue ry);
if (ERROR_SUCCESS != PdhGetFormattedCounterValu e(
m_pCounterStruct->hCounter ,
PDH_FMT_LONG,
NULL,
&pdhFormattedValue ))
{
return 0;
}
return pdhFormattedValue.longValu e;
}
remember to include pdh.h and link with pdh.lib.
To update this for harddrives change szCounterName[] = "\\PhysicalDisk(_Total)\\% Disk Time";
The _Total means all harddrives so if you want individual drives you must use their drive # ( can be found in disk administrator).
John
P.S. This code only works in NT 4.0, Win2k or XP. Because Win9X uses different perfomance monitor than nt4.0 +.
There is a wrapper class for Win9X that will allow you to read its performance counters at the following link:
http://www.naughter.com/dyndata.html
and
its not something you can read in a program, just for humans to read and see what the holdup is
You can read the performance monitor data in a C++ program. Here is code to read the CPU Usage:
// CpuUsage.h: interface for the CCpuUsage class.
//
//////////////////////////
#if !defined(AFX_CPUUSAGE_H__6
#define AFX_CPUUSAGE_H__60CF4F03_9
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define MAX_RAW_VALUES 20
const char szCounterName[] = "\\Processor(_Total)\\% Processor Time";
typedef struct _tag_PDHCounterStruct {
HCOUNTER hCounter; // Handle to the counter - given to use by PDH Library
int nNextIndex; // element to get the next raw value
int nOldestIndex; // element containing the oldes raw value
int nRawCount; // number of elements containing raw values
PDH_RAW_COUNTER a_RawValue[MAX_RAW_VALUES]
} PDHCOUNTERSTRUCT, *PPDHCOUNTERSTRUCT;
class CCpuUsage
{
public:
CCpuUsage();
virtual ~CCpuUsage();
BOOL Init();
int GetUsage();
protected:
PPDHCOUNTERSTRUCT m_pCounterStruct;
HQUERY m_hQuery;
};
#endif // !defined(AFX_CPUUSAGE_H__6
// CpuUsage.cpp: implementation of the CCpuUsage class.
//
//////////////////////////
#include "stdafx.h"
#include "CpuUsage.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////
// Construction/Destruction
//////////////////////////
CCpuUsage::CCpuUsage()
{
m_hQuery = NULL;
m_pCounterStruct = NULL;
}
CCpuUsage::~CCpuUsage()
{
PdhCloseQuery(m_hQuery);
delete m_pCounterStruct;
}
BOOL CCpuUsage::Init()
{
if (ERROR_SUCCESS != PdhOpenQuery(NULL, 1, &m_hQuery))
return FALSE;
m_pCounterStruct = (PPDHCOUNTERSTRUCT) new PDHCOUNTERSTRUCT;
PDH_STATUS pdh_status = PdhAddCounter(m_hQuery, szCounterName, (DWORD) m_pCounterStruct, &(m_pCounterStruct->hCount
if (ERROR_SUCCESS != pdh_status)
{
return FALSE;
}
return TRUE;
}
int CCpuUsage::GetUsage()
{
PDH_FMT_COUNTERVALUE pdhFormattedValue;
PdhCollectQueryData(m_hQue
if (ERROR_SUCCESS != PdhGetFormattedCounterValu
m_pCounterStruct->hCounter
PDH_FMT_LONG,
NULL,
&pdhFormattedValue ))
{
return 0;
}
return pdhFormattedValue.longValu
}
remember to include pdh.h and link with pdh.lib.
To update this for harddrives change szCounterName[] = "\\PhysicalDisk(_Total)\\%
The _Total means all harddrives so if you want individual drives you must use their drive # ( can be found in disk administrator).
John
P.S. This code only works in NT 4.0, Win2k or XP. Because Win9X uses different perfomance monitor than nt4.0 +.
There is a wrapper class for Win9X that will allow you to read its performance counters at the following link:
http://www.naughter.com/dyndata.html
and
ASKER
oh dear, i seem to have forgotten about this question. thanks for the info. For 50 extra points could you tell me the string to use for szCounterName for all the different monitors (CPU, HDD, MEM, etc.)
>could you tell me the string to use for szCounterName for all the different monitors (CPU, HDD, MEM, etc.)
There are too many to list.
CPU
\\Processor(_Total)\\% Processor Time
HDD
\\PhysicalDisk(_Total)\\% Disk Time
MEM
Depends on what you want.
To get the counters for different objects run perfmon from the run command of the start menu and click add.
The format for the string is \\<object name>(<instance>)\\<counte r> so in the cpu example:
object = Processor
instance = _Total
counter = % Processor Time
There are too many to list.
CPU
\\Processor(_Total)\\% Processor Time
HDD
\\PhysicalDisk(_Total)\\% Disk Time
MEM
Depends on what you want.
To get the counters for different objects run perfmon from the run command of the start menu and click add.
The format for the string is \\<object name>(<instance>)\\<counte
object = Processor
instance = _Total
counter = % Processor Time