Search code examples
pythonwindowswmiperformance-testingmetrics

How do I gather performance metrics for GDI and user Objects using python


Think this is my first question I have asked on here normally find all the answers I need (so thanks in advance)

ok my problem I have written a python program that will in threads monitor a process and output the results to a csv file for later. This code is working great I am using win32pdhutil for the counters and WMI, Win32_PerfRawData_PerfProc_Process for the CPU %time. I have now been asked to monitor a WPF application and specifically monitor User objects and GDI objects.

This is where I have a problem, it is that i can't seem to find any python support for gathering metrics on these two counters. these two counters are easily available in the task manager I find it odd that there is very little information on these two counters. I am specifically looking at gathering these to see if we have a memory leak, I don't want to install anything else on the system other than python that is already installed. Please can you peeps help with finding a solution.

I am using python 3.3.1, this will be running on a windows platform (mainly win7 and win8) This is the code i am using to gather the data

def gatherIt(self,whoIt,whatIt,type,wiggle,process_info2):
    #this is the data gathering function thing
    data=0.0
    data1="wobble"
    if type=="counter":
        #gather data according to the attibutes
        try:
            data = win32pdhutil.FindPerformanceAttributesByName(whoIt, counter=whatIt)
        except:
            #a problem occoured with process not being there not being there....
            data1="N/A"

    elif type=="cpu":
       try:
            process_info={}#used in the gather CPU bassed on service
            for x in range(2):
                for procP in wiggle.Win32_PerfRawData_PerfProc_Process(name=whoIt):
                    n1 = int(procP.PercentProcessorTime)
                    d1 = int(procP.Timestamp_Sys100NS)
                    #need to get the process id to change per cpu look...
                    n0, d0 = process_info.get (whoIt, (0, 0))     
                    try:
                        percent_processor_time = (float (n1 - n0) / float (d1 - d0)) *100.0
                        #print whoIt, percent_processor_time
                    except ZeroDivisionError:
                        percent_processor_time = 0.0
                    # pass back the n0 and d0
                    process_info[whoIt] = (n1, d1)
                #end for loop (this should take into account multiple cpu's)
            # end for range to allow for a current cpu time rather that cpu percent over sampleint
            if percent_processor_time==0.0:
                data=0.0
            else:
                data=percent_processor_time
        except:
            data1="N/A"

    else:
        #we have done something wrong so data =0
        data1="N/A"
    #endif
    if data == "[]":
        data=0.0
        data1="N/A"
    if data == "" :
        data=0.0
        data1="N/A"
    if data == " ":
        data=0.0
        data1="N/A"
    if data1!="wobble" and data==0.0:
        #we have not got the result we were expecting so add a n/a
        data=data1
    return data

cheers

edited for correct cpu timings issue if anyone tried to run it :D


Solution

  • so after a long search i was able to mash something together that gets me the info needed.

    import time
    from ctypes import *
    from ctypes.wintypes import *
    import win32pdh
    
    # with help from here http://coding.derkeiler.com/Archive/Python/comp.lang.python/2007-10/msg00717.html
    # the following has been mashed together to get the info needed
    
    def GetProcessID(name):
        object = "Process"
        items, instances = win32pdh.EnumObjectItems(None, None, object, win32pdh.PERF_DETAIL_WIZARD)
        val = None
        if name in instances :
            tenQuery = win32pdh.OpenQuery()
            tenarray = [ ]
            item = "ID Process"
            path = win32pdh.MakeCounterPath( ( None, object, name, None, 0, item ) )
            tenarray.append( win32pdh.AddCounter( tenQuery, path ) )
            win32pdh.CollectQueryData( tenQuery )
            time.sleep( 0.01 )
            win32pdh.CollectQueryData( tenQuery )
            for tencounter in tenarray:
                type, val = win32pdh.GetFormattedCounterValue( tencounter, win32pdh.PDH_FMT_LONG )
                win32pdh.RemoveCounter( tencounter )
            win32pdh.CloseQuery( tenQuery )
        return val
    
    processIDs = GetProcessID('OUTLOOK') # Remember this is case sensitive
    PQI = 0x400
    #open a handle on to the process so that we can query it
    OpenProcessHandle = windll.kernel32.OpenProcess(PQI, 0, processIDs)
    # OK so now we have opened the process now we want to query it
    GR_GDIOBJECTS, GR_USEROBJECTS = 0, 1
    print(windll.user32.GetGuiResources(OpenProcessHandle, GR_GDIOBJECTS))
    print(windll.user32.GetGuiResources(OpenProcessHandle, GR_USEROBJECTS))
    #so we have what we want we now close the process handle
    windll.kernel32.CloseHandle(OpenProcessHandle)
    

    hope that helps