home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Shareware / Comunicatii / jyte / jyte.exe / win32pdhutil.py < prev    next >
Text File  |  2003-09-08  |  6KB  |  139 lines

  1. """Utilities for the win32 Performance Data Helper module
  2.  
  3. Example:
  4.   To get a single bit of data:
  5.   >>> import win32pdhutil
  6.   >>> win32pdhutil.GetPerformanceAttributes("Memory", "Available Bytes")
  7.   6053888
  8.   >>> win32pdhutil.FindPerformanceAttributesByName("python", counter="Virtual Bytes")
  9.   [22278144]
  10.   
  11.   First example returns data which is not associated with any specific instance.
  12.   
  13.   The second example reads data for a specific instance - hence the list return - 
  14.   it would return one result for each instance of Python running.
  15.  
  16.   In general, it can be tricky finding exactly the "name" of the data you wish to query.  
  17.   Although you can use <om win32pdh.EnumObjectItems>(None,None,(eg)"Memory", -1) to do this, 
  18.   the easiest way is often to simply use PerfMon to find out the names.
  19. """
  20.  
  21. import win32pdh, string, time
  22.  
  23. error = win32pdh.error
  24.  
  25. # Handle some localization issues.
  26. # see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q287/1/59.asp&NoWebContent=1
  27. # Build a map of english_counter_name: counter_id
  28. counter_english_map = {}
  29.  
  30. def find_pdh_counter_localized_name(english_name, machine_name = None):
  31.     if not counter_english_map:
  32.         import win32api, win32con
  33.         counter_reg_value = win32api.RegQueryValueEx(win32con.HKEY_PERFORMANCE_DATA, "Counter 009")
  34.         counter_list = counter_reg_value[0]
  35.         for i in range(0, len(counter_list) - 1, 2):
  36.             try:
  37.                 counter_id = int(counter_list[i])
  38.             except ValueError:
  39.                 continue
  40.             counter_english_map[counter_list[i+1].lower()] = counter_id
  41.     return win32pdh.LookupPerfNameByIndex(machine_name, counter_english_map[english_name.lower()])
  42.  
  43. def GetPerformanceAttributes(object, counter, instance = None, inum=-1, format = win32pdh.PDH_FMT_LONG, machine=None):
  44.     # NOTE: If you attempt to use this function to get "% Processor Time",
  45.     # it will not work as you expect - the problem is that by creating a
  46.     # new query each time, we force the CPU to 100%.  If you pull this
  47.     # function apart, and only do the inner "CollectQueryData" each time
  48.     # you need to know, it will give the correct results.
  49.     path = win32pdh.MakeCounterPath( (machine,object,instance, None, inum,counter) )
  50.     hq = win32pdh.OpenQuery()
  51.     try:
  52.         hc = win32pdh.AddCounter(hq, path)
  53.         try:
  54.             win32pdh.CollectQueryData(hq)
  55.             type, val = win32pdh.GetFormattedCounterValue(hc, format)
  56.             return val
  57.         finally:
  58.             win32pdh.RemoveCounter(hc)
  59.     finally:
  60.         win32pdh.CloseQuery(hq)
  61.  
  62. def FindPerformanceAttributesByName(instanceName, object = None, counter = None, format = win32pdh.PDH_FMT_LONG, machine = None, bRefresh=0):
  63.     """Find peformance attributes by (case insensitive) instance name.
  64.     
  65.     Given a process name, return a list with the requested attributes.
  66.     Most useful for returning a tuple of PIDs given a process name.
  67.     """
  68.     if object is None: object = find_pdh_counter_localized_name("Process", machine)
  69.     if counter is None: counter = find_pdh_counter_localized_name("ID Process", machine)
  70.     if bRefresh: # PDH docs say this is how you do a refresh.
  71.         win32pdh.EnumObjects(None, machine, 0, 1)
  72.     instanceName = string.lower(instanceName)
  73.     items, instances = win32pdh.EnumObjectItems(None,None,object, -1)
  74.     # Track multiple instances.
  75.     instance_dict = {}
  76.     for instance in instances:
  77.         try:
  78.             instance_dict[instance] = instance_dict[instance] + 1
  79.         except KeyError:
  80.             instance_dict[instance] = 0
  81.         
  82.     ret = []
  83.     for instance, max_instances in instance_dict.items():
  84.         for inum in xrange(max_instances+1):
  85.             if string.lower(instance) == instanceName:
  86.                 ret.append(GetPerformanceAttributes(object, counter, instance, inum, format, machine))
  87.     return ret
  88.  
  89. def ShowAllProcesses():
  90.     object = "Process"
  91.     items, instances = win32pdh.EnumObjectItems(None,None,object, win32pdh.PERF_DETAIL_WIZARD)
  92.     # Need to track multiple instances of the same name.
  93.     instance_dict = {}
  94.     for instance in instances:
  95.         try:
  96.             instance_dict[instance] = instance_dict[instance] + 1
  97.         except KeyError:
  98.             instance_dict[instance] = 0
  99.         
  100.     # Bit of a hack to get useful info.
  101.     items = ["ID Process"] + items[:5]
  102.     print "Process Name", string.join(items,",")
  103.     for instance, max_instances in instance_dict.items():
  104.         for inum in xrange(max_instances+1):
  105.             hq = win32pdh.OpenQuery()
  106.             hcs = []
  107.             for item in items:
  108.                 path = win32pdh.MakeCounterPath( (None,object,instance, None, inum, item) )
  109.                 hcs.append(win32pdh.AddCounter(hq, path))
  110.             win32pdh.CollectQueryData(hq)
  111.             # as per http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262938, some "%" based
  112.             # counters need two collections
  113.             time.sleep(0.01)
  114.             win32pdh.CollectQueryData(hq)
  115.             print "%-15s\t" % (instance[:15]),
  116.             for hc in hcs:
  117.                 type, val = win32pdh.GetFormattedCounterValue(hc, win32pdh.PDH_FMT_LONG)
  118.                 print "%5d" % (val),
  119.                 win32pdh.RemoveCounter(hc)
  120.             print
  121.             win32pdh.CloseQuery(hq)
  122.  
  123. def BrowseCallBackDemo(counter):
  124.     machine, object, instance, parentInstance, index, counterName = \
  125.         win32pdh.ParseCounterPath(counter)
  126.  
  127.     result = GetPerformanceAttributes(object, counterName, instance, index, win32pdh.PDH_FMT_DOUBLE, machine)
  128.     print "Value of '%s' is" % counter, result
  129.     print "Added '%s' on object '%s' (machine %s), instance %s(%d)-parent of %s" % (counterName, object, machine, instance, index, parentInstance)
  130.  
  131. def browse( callback = BrowseCallBackDemo, title="Python Browser", level=win32pdh.PERF_DETAIL_WIZARD):
  132.     print "Virtual Bytes = ", FindPerformanceAttributesByName("python", counter="Virtual Bytes")     
  133.     print "Available Bytes = ", GetPerformanceAttributes("Memory", "Available Bytes")
  134.  
  135. if __name__=='__main__':
  136.     ShowAllProcesses()
  137.     print "Browsing for counters..."
  138.     browse()
  139.