Results 1 to 9 of 9

Thread: Disk Activity Monitor for multiple disks

  1. #1

    Thread Starter
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Disk Activity Monitor for multiple disks

    I'm adding a second hard drive -- woohoo! -- and was wondering how to update my hard drive activity monitor to differentiate activity between the two physical drives.

    Looking at the code I use for the activity monitor (which I've been using and loving for almost a decade now) I'm not seeing any reference to a particular drive anywhere.

    clsHDMon.cls:
    vb Code:
    1. ' // Written by Ellis Dee //
    2. ' Thanks to Matt Pietrek of MSJ and Edgemeal of vbforums.com
    3. Option Explicit
    4.  
    5. Public Event Activity()
    6. Public Event Idle()
    7.  
    8. Private Const ReadColor = 16761024 ' ?RGB(192, 192, 255)
    9. Private Const WriteColor = 16744576 ' ?RGB(128, 128, 255)
    10. Private Const InactiveColor = 6316128  ' ?RGB(96, 96, 96)
    11. Private Const BorderColor = 0 ' ?RGB(0, 0, 0)
    12.  
    13. Private mlngRead As Long
    14. Private mlngWrite As Long
    15. Private mlngIdle As Long
    16. Private mblnIndicator As Boolean
    17.  
    18. Private mblnValid As Boolean
    19. Private mlngQuery As Long
    20. Private mlngReadCounter As Long
    21. Private mlngWriteCounter As Long
    22.  
    23. Private Const ERROR_SUCCESS = 0
    24.  
    25. Private Enum PDH_STATUS
    26.     PDH_CSTATUS_VALID_DATA = &H0
    27.     PDH_CSTATUS_NEW_DATA = &H1
    28.     PDH_CSTATUS_NO_MACHINE = &H800007D0
    29.     PDH_CSTATUS_NO_INSTANCE = &H800007D1
    30.     PDH_MORE_DATA = &H800007D2
    31.     PDH_CSTATUS_ITEM_NOT_VALIDATED = &H800007D3
    32.     PDH_RETRY = &H800007D4
    33.     PDH_NO_DATA = &H800007D5
    34.     PDH_CALC_NEGATIVE_DENOMINATOR = &H800007D6
    35.     PDH_CALC_NEGATIVE_TIMEBASE = &H800007D7
    36.     PDH_CALC_NEGATIVE_VALUE = &H800007D8
    37.     PDH_DIALOG_CANCELLED = &H800007D9
    38.     PDH_CSTATUS_NO_OBJECT = &HC0000BB8
    39.     PDH_CSTATUS_NO_COUNTER = &HC0000BB9
    40.     PDH_CSTATUS_INVALID_DATA = &HC0000BBA
    41.     PDH_MEMORY_ALLOCATION_FAILURE = &HC0000BBB
    42.     PDH_INVALID_HANDLE = &HC0000BBC
    43.     PDH_INVALID_ARGUMENT = &HC0000BBD
    44.     PDH_FUNCTION_NOT_FOUND = &HC0000BBE
    45.     PDH_CSTATUS_NO_COUNTERNAME = &HC0000BBF
    46.     PDH_CSTATUS_BAD_COUNTERNAME = &HC0000BC0
    47.     PDH_INVALID_BUFFER = &HC0000BC1
    48.     PDH_INSUFFICIENT_BUFFER = &HC0000BC2
    49.     PDH_CANNOT_CONNECT_MACHINE = &HC0000BC3
    50.     PDH_INVALID_PATH = &HC0000BC4
    51.     PDH_INVALID_INSTANCE = &HC0000BC5
    52.     PDH_INVALID_DATA = &HC0000BC6
    53.     PDH_NO_DIALOG_DATA = &HC0000BC7
    54.     PDH_CANNOT_READ_NAME_STRINGS = &HC0000BC8
    55. End Enum
    56.  
    57. Private Declare Function PdhVbGetOneCounterPath Lib "PDH.DLL" (ByVal PathString As String, ByVal PathLength As Long, ByVal DetailLevel As Long, ByVal CaptionString As String) As Long
    58. Private Declare Function PdhVbCreateCounterPathList Lib "PDH.DLL" (ByVal PERF_DETAIL As Long, ByVal CaptionString As String) As Long
    59. Private Declare Function PdhVbGetCounterPathFromList Lib "PDH.DLL" (ByVal Index As Long, ByVal Buffer As String, ByVal BufferLength As Long) As Long
    60. Private Declare Function PdhOpenQuery Lib "PDH.DLL" (ByVal Reserved As Long, ByVal dwUserData As Long, ByRef mlngQuery As Long) As PDH_STATUS
    61. Private Declare Function PdhCloseQuery Lib "PDH.DLL" (ByVal mlngQuery As Long) As PDH_STATUS
    62. Private Declare Function PdhVbAddCounter Lib "PDH.DLL" (ByVal QueryHandle As Long, ByVal CounterPath As String, ByRef CounterHandle As Long) As PDH_STATUS
    63. Private Declare Function PdhCollectQueryData Lib "PDH.DLL" (ByVal QueryHandle As Long) As PDH_STATUS
    64. Private Declare Function PdhVbIsGoodStatus Lib "PDH.DLL" (ByVal StatusValue As Long) As Long
    65. Private Declare Function PdhVbGetDoubleCounterValue Lib "PDH.DLL" (ByVal CounterHandle As Long, ByRef CounterStatus As Long) As Double
    66.  
    67. Public Sub GetActivity(plngRead As Long, plngWrite As Long)
    68.     If mblnValid Then
    69.         PdhCollectQueryData (mlngQuery)
    70.         plngRead = GetCounter(mlngReadCounter) ' PhysicalDisk Total % Disk Read Time
    71.         plngWrite = GetCounter(mlngWriteCounter) ' PhysicalDisk Total % Disk Write Time
    72.     End If
    73. End Sub
    74.  
    75. Private Function GetCounter(plngCounter As Long) As Long
    76.     Dim enStatus As PDH_STATUS
    77.     Dim dblActivity As Double
    78.    
    79.     dblActivity = PdhVbGetDoubleCounterValue(plngCounter, enStatus)
    80.     ' Verify that when we queried, the returned value was valid
    81.     If Not ((enStatus = PDH_CSTATUS_VALID_DATA) Or (enStatus = PDH_CSTATUS_NEW_DATA)) Then dblActivity = 0
    82.     Select Case dblActivity
    83.         Case Is < 10: GetCounter = 0
    84.         Case Is > 100: GetCounter = 5
    85.         Case Else: GetCounter = 1 + (Round(dblActivity) - 1) \ 20
    86.     End Select
    87. End Function
    88.  
    89. Private Sub Class_Initialize()
    90.     StartMonitor
    91. End Sub
    92.  
    93. Private Sub Class_Terminate()
    94.     StopMonitor
    95. End Sub
    96.  
    97. Public Sub StopMonitor()
    98.     If mlngQuery Then PdhCloseQuery (mlngQuery) ' Free the PDH query
    99.     mblnValid = False
    100. End Sub
    101.  
    102. Public Sub StartMonitor()
    103.     Dim enStatus As PDH_STATUS
    104.    
    105.     enStatus = PdhOpenQuery(0, 1, mlngQuery)
    106.     If enStatus <> ERROR_SUCCESS Then Exit Sub
    107.     mblnValid = True
    108.     PdhVbAddCounter mlngQuery, "\PhysicalDisk(_Total)\% Disk Read Time", mlngReadCounter
    109.     PdhVbAddCounter mlngQuery, "\PhysicalDisk(_Total)\% Disk Write Time", mlngWriteCounter
    110. End Sub
    111.  
    112. Public Sub Timer(ppic As PictureBox)
    113.     Dim lngNewRead As Long
    114.     Dim lngNewWrite As Long
    115.     Dim blnRedraw As Boolean
    116.     Dim blnOldIndicator As Boolean
    117.    
    118.     If Not mblnValid Then Exit Sub
    119.     blnOldIndicator = mblnIndicator
    120.     Me.GetActivity lngNewRead, lngNewWrite
    121.     If lngNewRead = 0 And lngNewWrite = 0 Then
    122.         mlngIdle = mlngIdle + 1
    123.         mblnIndicator = (mlngIdle < 15)
    124.     Else
    125.         mblnIndicator = True
    126.         mlngIdle = 0
    127.     End If
    128.     If lngNewRead <> mlngRead Then
    129.         mlngRead = lngNewRead
    130.         blnRedraw = True
    131.     End If
    132.     If lngNewWrite <> mlngWrite Then
    133.         mlngWrite = lngNewWrite
    134.         blnRedraw = True
    135.     End If
    136.     If mblnIndicator Then
    137.         If blnRedraw Then
    138.             ppic.Line (0, 0)-(31, 31), BorderColor, BF
    139.             DrawIndicator ppic, mlngRead, ReadColor, 2
    140.             DrawIndicator ppic, mlngWrite, WriteColor, 17
    141.             RaiseEvent Activity
    142.         End If
    143.     ElseIf blnOldIndicator Then
    144.         RaiseEvent Idle
    145.     End If
    146. End Sub
    147.  
    148. Private Sub DrawIndicator(ppic As PictureBox, plngActivity As Long, plngColor As Long, plngLeft As Long)
    149.     Dim lngRight As Long
    150.     Dim lngColor As Long
    151.     Dim lngY As Long
    152.     Dim i As Long
    153.    
    154.     lngRight = plngLeft + 12
    155.     For i = 0 To 4
    156.         If i < plngActivity Then lngColor = plngColor Else lngColor = InactiveColor
    157.         lngY = 26 - i * 6
    158.         ppic.Line (plngLeft, lngY)-(lngRight, lngY + 3), lngColor, BF
    159.     Next
    160. End Sub
    My indicator light is just a simple userdrawn picturebox, and right now looks like this in practice, with reads on the left and writes on the right:

    Name:  Icon-Active.png
Views: 679
Size:  15.5 KB

    Conceptually, I'm not quite sure yet how I want to show two drive indicators in the same icon, but first I need to figure out if I can even set up independent monitors for both physical drives.

    EDIT: After around 3-4 seconds of inactivity, it reverts to a static icon:

    Name:  Icon-Inactive.png
Views: 685
Size:  19.2 KB

    This program does more than just monitor hard drive activity. It's my place to put any utilities I write and want easy access to, like for instance my backup routine that I'm absolutely loving. The indicator is merely the justification for it taking up icon space in the tray.
    Last edited by Ellis Dee; May 2nd, 2016 at 05:16 AM.

  2. #2
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,296

    Re: Disk Activity Monitor for multiple disks

    [...]
    Last edited by dz32; Apr 26th, 2019 at 12:02 PM.

  3. #3
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Re: Disk Activity Monitor for multiple disks

    I use an app that uses that string format for perfmon meters... selecting an individual disk looks like \PhysicalDisk(3 G:)\% Disk Read Time

    where the first drive is (0 E:), which is odd since it's not the primary disk, C:\, which has the OS and is on SATA 0.

  4. #4

    Thread Starter
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: Disk Activity Monitor for multiple disks

    Cool, that's at least a place to start. Thanks much.

    I'll post back here with follow-up questions and/or results once I get my second drive installed.

    For the class itself, I'm thinking enumerate the hard drives on class_init and then branch off to either this existing code for single-drive systems or a new branch for two-drive systems. I won't be able to test single-drive systems any longer, sadly, but not a huge deal. This code has worked well for all my computers since writing it: XP, 7 and 10.

  5. #5

    Thread Starter
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: Disk Activity Monitor for multiple disks

    In the meantime, anyone have any ideas/suggestions for how to show activity on two drives in a single icon?

    The most obvious is splitting the indicator vertically, so the left side (currently light blue reads) would be two narrow columns showing reads and writes for the system drive and the right side (currently dark blue writes) would be two narrow columns for the data drive. Probably different colors; maybe greens for the data drives?

    Another option would be four square quadrants, with the tops being reads and the bottoms writes, left system right data. Activity levels could be represented by either making the squares bigger/smaller, or maybe using color gradients: darker = less activity, brighter = more activity.

    Another possibly ugly option might be to leave the primary indicator exactly as-is, but add the secondary indicator to the negative space. (The dark "background" lines between indicator lines.) This option would live or die based on colors chosen, I think.

    Any other ideas?

    EDIT: Another option could be to leave the read and write columns alone (I kind of like their dimensions, having gotten very used to it over the past decade) and use colors to denote what's going on:

    Blues = system drive only
    Greens = data drive only
    Purples = both drives

    Or whatever colors end up working. The idea here would be to combine both drives into one bar. So, just throwing out examples, if the system drive is being read at 40% (two bars) and the data drive is being read at 80% (four bars) the read indicator's five lines, from top to bottom, would be:

    5 (<=100%): Dark Gray (background color)
    4 (<=80%): Green
    3 (<=60%): Green
    2 (<=40%): Purple
    1 (<=20%): Purple

    This again would live and die based on colors chosen.
    Last edited by Ellis Dee; May 2nd, 2016 at 10:04 PM.

  6. #6
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Re: Disk Activity Monitor for multiple disks

    Splitting vertically seems to me the most intuitive option.. keep the colors and two bars that exist now, and vertically split each bar with reads in one column and writes in the other. Any more than two drives just won't look good at that icon size though.

  7. #7

    Thread Starter
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: Disk Activity Monitor for multiple disks

    Quote Originally Posted by fafalone View Post
    Splitting vertically seems to me the most intuitive option.. keep the colors and two bars that exist now, and vertically split each bar with reads in one column and writes in the other. Any more than two drives just won't look good at that icon size though.
    This was my first choice, but after throwing together some mockups I don't think there's enough width on split columns to be readily seen at a glance.

    Here's a mockup of the split columns, blue and green:
    Name:  Icon-Split.png
Views: 529
Size:  16.6 KB

    Here's a mockup of the four quadrants, with larger dots denoting more activity:
    Name:  Icon-Boxes.png
Views: 518
Size:  15.4 KB

    Here's a mockup of four quadrants always filled, with brightness indicating activity:
    Name:  Icon-BoxColors.png
Views: 509
Size:  15.4 KB

    Here's a mockup of using a third color to depict activity on both drives:
    Name:  Icon-Combo.png
Views: 536
Size:  15.6 KB

    Not really loving any of these so far, but of course I haven't tweaked any of the colors to really work. (These were quickly thrown together.)

    Another possibility is a hybrid of the three-colors option. Something like use blue if activity is mostly system, green if mostly data, or yellow if roughly equal on both. So like 60% system 20% data would be considered mostly system and show as blue, while 40% on both would show as combined yellow. All bars would stick to a single color scheme regardless of value.

    This is the most pleasing for static screenshots, but could become a flickering nightmare in practice.

  8. #8

    Thread Starter
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: Disk Activity Monitor for multiple disks

    Actually, now that I'm running my backup in preparation for adding the second hard drive I'm noticing that my disk monitor is showing writes to the flash drive. And I kind of like it. Given that, I think I might just stick with the global "any activity" unified indicator.

    Name:  Flash Indicator.jpg
Views: 563
Size:  41.4 KB

    Man this Ultra is slooooooow. hehheh.
    Last edited by Ellis Dee; May 3rd, 2016 at 02:39 PM.

  9. #9
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Re: Disk Activity Monitor for multiple disks

    Yeah 'Physical Disk' will include flash drives, or any mass storage on USB, but not network drives even if mapped to a letter. If a physical disk has multiple partitions, it would still be seen as a single disk ('LogicalDisk' will show all the partitions as different drives, but again no network mapped drives).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width