Jump to content

Performance Counters in Windows - Measure Process, CPU, Network, Disk Usage


Ascend4nt
 Share

Recommended Posts

ok found a solution for the ram.

But pdh functions seems to works only in admin account :graduated: Script doesn't work as user that isn't in AD administrators. odd.

What was the memory problem? There shouldn't be any problems with memory usage... or was it some other part of your program? (Actually, there is an issue with PdhBrowseCounters loading DLL's that never get released - MS bug - but thats only if you call that _PDH_BrowserCounters() in your script)

As far as the PDH functions working only on Admin accounts - this is untrue. I just tested this on a limited user account. The only case where the PDH performance counters will fail is if it is disabled in the registry somewhere for non-admin accounts. Try calling _PDH_RegistryCheck() and seeing what it returns. Also, you can set $PDH_DEBUGLOG to 2 at the top of your script to get more information reported to the console.

Link to comment
Share on other sites

Thanks for support !

About memory, I don't anymore init/uninit pdh in the function, I init it at beginning of the script once.

Here is the new function :

Func _PDH_countcpu()
;_PDH_Init()
$hPDHQuery = _PDH_GetNewQueryHandle()
$hCPUCounter = _PDH_AddCounter($hPDHQuery,":238\6\(_Total)")
_PDH_CollectQueryData($hPDHQuery) ; collect the query information once (1st collection may fail, so we'll discard it)
Sleep(50)
While 1
  $iCPUUsage = _PDH_UpdateCounter($hPDHQuery,$hCPUCounter)  ; collect query info and then grab counter value
  If Not @error Then ExitLoop
  Sleep(50)
WEnd
Sleep(50)
_PDH_FreeQueryHandle($hPDHQuery)
;_PDH_UnInit($hPDHQuery)
EndFunc

About admin or not, thanks for the infos, I will check what you say, hope it will work cause your udf is just plenty amazing. I'm network admin also so no problem changing things in AD/GPOs if needed.

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

I found this in toggle function :

"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib"

"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfOS\Performance"

"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfProc\Performance"

but which keys/values ?

Edited by kiboost

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

Ok, here is the debug log on the nonworking machine (exact same script working on another one) :

working one : old Amd-DualCore 4600

unworking : Core i7 920 (multithreading)

both win7pro x64 french

registry keys seems the same for both machines

_PDH_GetNewQueryHandle Call succeeded, return:0,param1:0x0000000000000000,param2:0,handle:0x0000000003A512F0

_PDH_GetCounterNameByIndex() call, Index:238 [optional] Machine Name:, PDH DLL 'handle' (or just 'pdh.dll'):1

_PDH_GetCounterNameByIndex() call, Index:6 [optional] Machine Name:, PDH DLL 'handle' (or just 'pdh.dll'):1

Localized counter (from non-localized string):\(_Total)\

PdhAddCounterW error [path:'\(_Total)\'], return:C0000BB8

PdhCollectQueryData error, return:800007D5

Edited by kiboost

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

Okay, it appears there's a problem in the _PDH_GetCounterNameByIndex() function. Try running this, it should return a string that is the french equivalent of 'Processor':

Local $iIndex=238
Local $aRet=DllCall('pdh.dll',"long","PdhLookupPerfNameByIndexW",'ptr',0,"dword",$iIndex,"wstr","","dword*",65536)
If @error Then Exit ConsoleWrite("Error on PdhLookupPerfNameByIndexW call:"&@error&@CRLF)
If $aRet[0] Then Exit ConsoleWrite("_PDH_GetCounterNameByIndex non-zero error code:" & Hex($aRet[0])&@CRLF)
ConsoleWrite("PdhLookupPerfNameByIndexW results: Index:"&$aRet[3]&@CRLF)
Link to comment
Share on other sites

with TestPDH_PerformanceCounters.au3 on unworking machine :

running processor information, the counters seems to work (counter numbers updates with activity) but when clicking on %processor time I got this in console :

New ID from ctListView:29

_PDHGetCounterIndex non-zero error code:C0000BD4

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

Okay, 1 thing at a time... we need to figure out why it can't find the registry string corresponding to the index # given. Perhaps try the ANSI version of that function? (I don't know how well this would work on a French PC, but wth, give it a try):

Local $iIndex=238
Local $aRet=DllCall('pdh.dll',"long","PdhLookupPerfNameByIndexA",'ptr',0,"dword",$iIndex,"str","","dword*",65536)
If @error Then Exit ConsoleWrite("Error on PdhLookupPerfNameByIndex call:"&@error&@CRLF)
If $aRet[0] Then Exit ConsoleWrite("_PDH_GetCounterNameByIndex non-zero error code:" & Hex($aRet[0])&@CRLF)
ConsoleWrite("PdhLookupPerfNameByIndex results: Index string:"&$aRet[3]&", #chars:"&$aRet[4]&@CRLF)

If that still gives a blank string after Index, check the registry as outlined on MSDN in PdhLookupPerfNameByIndex. '009' is the English language key, so check the other keys. See which of them have a 'Counter' value with a REG_MULTI_SZ string consisting of "# String" pairs. Here's the branch as seen on MSDN (leading dots added):

HKEY_LOCAL_MACHINE

....\SOFTWARE

......\Microsoft

.........\Windows NT

............\CurrentVersion

...............\Perflib

..................Last Counter = highest counter index

..................Last Help = highest help index

..................\009

.....................Counters = 2 System 4 Memory...

.....................Help = 3 The System Object Type...

..................\supported language, other than English

.....................Counters = ...

.....................Help = ...

HMM.. now that I think about it - if you can put a '$PDH_DEBUGLOG = 2' in TestPDH_PerformanceCounters.au3 (after #include <_PDH_PerformanceCounters.au3>), we'll have an idea of what strings are being returned from the BrowseCounters dialog too.

Sorry to put ya to work on debugging this, but I've never seen this problem and don't have a French language PC. In the end we *might* look at PdhAddEnglishCounter (something I explored in an ).

Link to comment
Share on other sites

ok, no problem debugging, this is part of coding tasks. Thank you for your time.

Ansi debug :

working : PdhLookupPerfNameByIndex results: Index string:Processeur, #chars:11

unworking : PdhLookupPerfNameByIndex results: Index string:, #chars:65536

now on registry, I have 009 on both, but :

working : I have Conter and Help, REG_MULTI_SZ, with values. and indeed :

6

% Processor Time

unworking : I have the same keys, but none have values ! just nothing !

It is the same for 009, 00C, CurrentLanguage

Can I try to export working values and import them on unworking machine ? Would do the trick ? Would be sure it won't fuck anything else.

Edit : same for keys in wow6432Node

Edit2 : keys are not empty on unworking machines ! they begin at 6622 wmiobjects and then seems the same ! But all beggining lines till 6622 are there but blank ! Also in computer/properties, checking performance index/evaluate I get an error "command passed to winsat is invalid"

Strange ...

Edit 3 : have found that : http://support.microsoft.com/kb/300956/en-us

Edited by kiboost

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

ok, found the solution (well, thank you for pointing to right direction, and thanks to ms kb)

I just run the cmd lodctr /R as administrator. it reconstruct perf counters and voilà !

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

kiboot, I'm glad you solved the problem. I'm curious though, how many machines have you found this problem on? And what do you suppose cause the screwed up data in the registry? Were they special installs? I'm just trying to figure out if this problem could be commonplace or not.

Well, either way its not something I can control. Its good to have the info documented here in the thread though for anyone that comes upon the same problem. Thanks

Link to comment
Share on other sites

I've think about that and can't think of what caused this. All machines are pretty similar, all windows7 where deployed using same tools, and all updates are done with same deployment script, so it is strange. Anyway, I had only 2 machines with this over 35. The solution solved it for both.

Once more, thanks for your time regarding this, and thanks even more for this udf ! Autoit community is really powerfull due to people like you ;-)

Win7 pro x64. scripts compiled to x64. - Autoit v3.3.6.1 | Scite 1.79

Link to comment
Share on other sites

  • 2 months later...

Hi Ascend4nt

I saw your wonderful UDF some days ago.

I tried to monitor my HDD load.

But with the following script, I always get an error.

Please can you help me find the error? I think it would be a stupid small thing!

#include "_PDH_PerformanceCounters.au3"
#include <Array.au3>
_PDH_Init(False, False)
$hPDH = _PDH_GetNewQueryHandle()
$hPDHCounter = _PDH_AddCounter($hPDH, ":234\200\(_Total)") ;=> Physical Disk (_Total) Time in percent
;~ $aTest = _PDH_GetCounterInfo($hPDHCounter)
;~ _ArrayDisplay($aTest)
MsgBox(0,"",_PDH_UpdateCounter($hPDH, $hPDHCounter))

_PDH_FreeQueryHandle($hPDH)
_PDH_UnInit()
Exit

It returns always -1 and the message code is: "Error Calling PdhGetFormattedCounterValue for Handle:0x02B01928, Path [if passed]:, Return:C0000BC6"

Thanks in advance!

Best regards

Veronesi

Link to comment
Share on other sites

Sorry, I think I have the solution.

#include "S:\WSP\Source\Functions\_PDH_PerformanceCounters.au3"
OnAutoItExitRegister("_Exit")
HotKeySet("{ESC}", "_Exit")
_PDH_Init(False, False)
$hPDH = _PDH_GetNewQueryHandle()
$hPDHCounter = _PDH_AddCounter($hPDH, ":234\200\(_Total)") ;=> Physical Disk (_Total) Time in percent
_PDH_CollectQueryData($hPDH)
While Sleep(200)
$timer = TimerInit()
ToolTip("HDD-Load: " & _PDH_UpdateCounter($hPDH, $hPDHCounter, "", False) & " / Used Time: " & Round(TimerDiff($timer), 4) & "ms")
WEnd
_Exit()
Func _Exit()
_PDH_FreeQueryHandle($hPDH)
_PDH_UnInit()
Exit
EndFunc
Link to comment
Share on other sites

Interesting, I wasn't aware of that command. Thanks for the tip, rcmaehl.

That command line function of course has limitations:

  • You have to decide whether you want your program to sit there and constantly read the output of the function, or run the program every so often. Each has its drawbacks, and many counters require a baseline read before giving a valid value on the 2nd read.
  • There is no control over what format the data is returned as. My UDF does specify int64 as the type, but this can be tweaked (manually for now). Also, my UDF will make adjustments for the # of CPU's present so that the values returned match those in Task Manager.
  • The command line offers no numerical counter support. This is important for non-English Operating Systems, and it was one of the issues that I solved with a relatively simple solution in my UDF.
  • Even if you used my functions to convert numerical counter values to strings, there would be the question of whether 'typeperf' accepts Unicode input. (I can't test this myself as I have an English O/S).
I'm sure there's situations where typeperf can be useful, but its not a very flexible or elegant solution.

There's also WMI alternative "Win32_PerfFormattedData" variants, which I've seen used on the forums. They are slower than PDH though.

Thanks!

Link to comment
Share on other sites

No problem. However, typeperf is only available on Windows XP Professional and Newer which may be a problem for if you use typeperf at all. (Unless you provide it and it's dlls with your script.)

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Link to comment
Share on other sites

  • 2 months later...

Hi,

how can i combine two counters in one script?

I would like to get the results of CPU-Usage and Network-Usage in one script.

Did i get wrong results 'cause (e.g.) there is only one call for _PDH_GetNewQueryHandle?

Thanks

Dizzy

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...