HDD_LED - OPERATION AND OPTIONS =============================== 1. OVERVIEW ----------- hdd_led puts a small "LED" on the Windows desktop for every disk drive letter (C:, D:, ...). The LED is green while the drive is idle and red while it is reading or writing. Hovering the mouse over an LED shows a tooltip with the current read and write speed, I/O operations per second, the total bytes read and written, free space, and the programs that are most likely responsible for the activity. Everything is in one Python file, hdd_led.py. It uses only the Python standard library (ctypes and tkinter) - there is nothing to pip install. 2. REQUIREMENTS --------------- * Windows 10 or Windows 11 * Python 3.12 or newer, with tkinter (included in the standard installer from python.org; leave "tcl/tk and IDLE" ticked) * The Windows performance counters must be working (they are by default) No administrator rights are needed. 3. RUNNING THE PROGRAM ---------------------- Without a console window (normal use): pythonw hdd_led.py With a console window (needed to see messages or to use Ctrl-C): python hdd_led.py Building a stand-alone .exe (optional): pip install pyinstaller pyinstaller --noconsole --onefile hdd_led.py The exe appears in the "dist" folder. Build it WITHOUT --noconsole if you want a console window with the Ctrl-C messages described in section 9. Only one copy runs at a time. Starting a second copy exits immediately. 4. THE INDICATORS ----------------- Which drives get an LED * One LED per drive letter: fixed disks, USB/external disks, removable drives and card readers (only while media is present), optical drives (only while a disc is present), RAM disks and mapped network drives. * Floppy letters A: and B: and volumes that are only mounted in a folder (no drive letter) are not shown. * Drives are looked up again every two seconds, so plugging in or removing a drive is noticed automatically. A drive that comes back keeps its saved position. Colours * Idle colour (default green): no I/O. * Active colour (default red): the drive is reading or writing. * Separate read/write colours (default OFF): when the option "Use separate colours for read-only / write-only" is ticked in Settings, the LED uses read-only activity the read colour (default amber) write-only activity the write colour (default blue) reading AND writing the active colour (default red) "Read-only" and "write-only" are judged by the dominant direction: if one direction is below 10% of the other (for example a few KB/s of file-system housekeeping writes during a large file read), it is treated as background and ignored. Genuinely mixed activity still shows the active colour. With the option OFF, every kind of activity shows the active colour. * Unavailable colour (default grey): the drive is listed but Windows provides no activity data for it (for example a virtual or cloud drive). The tooltip says why. Grey LEDs can be switched off in Settings. * A short "minimum red time" (default 80 ms) keeps very brief I/O bursts visible. Where the activity numbers come from Local drives Windows "LogicalDisk" performance counters. Network drives Windows "SMB Client Shares" counters. The drive letter is matched to its \\server\share. Network drives that are not SMB shares cannot be measured (grey LED). Raw-disk fallback (local drives only) The volume counters only see I/O that goes through the file system. Tools that read the disk directly (imaging, cloning, benchmarks, some backup programs) are invisible to them. For a drive that is the ONLY lettered volume on its physical disk, the program also reads the physical-disk counters and uses whichever shows clearly more activity. The tooltip then shows "Source: physical disk N (raw access)". The fallback is not used when several lettered volumes share one disk (the activity cannot be assigned to one of them). It can be turned off in Settings. Self-healing and responsiveness * If a drive's counters return no data for about three seconds (typically after the drive was ejected and re-inserted), the program rebuilds them automatically. Grey LEDs are retried every two seconds. * Drive details (label, free space, which physical disk holds a volume) are gathered on a background thread, because Windows can take many seconds to answer for a sleeping, disconnected or faulty drive, especially a network drive. Such a drive can delay its own details but can never freeze the LEDs or the rest of the program. Network drives are never opened to look up a physical disk. Window behaviour * LEDs have no taskbar button. They are always on top by default (see "Always on top" in Settings). * The shape is a circle or a square. Around a circle the corners are fully transparent, and mouse clicks pass through them. * When "always on top" is on, the program re-asserts it every two seconds, because Windows occasionally drops the topmost state. Default position Along the top edge of the screen, with the first LED 30% of the screen width from the left edge. Further drives are placed side by side to its right, in drive-letter order. This applies to every drive that has no saved position. 5. MOUSE OPERATION ------------------ Hover Show the tooltip (after a quarter of a second). It updates live while you stay on the LED. Left-drag Move the LED (unless "Lock position" is on). Right-click Open the context menu (section 6). 6. CONTEXT MENU (right-click an LED) ------------------------------------ - Open in Explorer Open the drive in a File Explorer window. Settings... Open the settings window (section 7). Hide Remove that LED. Bring it back in Settings under "Volumes to show". Reset positions Forget all saved positions and return the LEDs to the default layout (section 4). Reset totals Set all "total read / written" counters to zero and restart the "since" time. Diagnostics... Open the live diagnostics window (section 11). Exit Save settings and quit. 7. SETTINGS WINDOW ------------------ OK applies and closes, Apply applies and keeps the window open, Cancel discards changes. Settings are stored automatically (section 10). Appearance Size (px) LED diameter. 12 to 96. Default 28. Opacity (%) 20 to 100. Default 90. Shape circle or square. Default circle. Idle colour Default green (#22c55e). Active colour Default red (#ef4444). Read-only colour Default amber (#f59e0b). Used only when separate colours are enabled. Write-only colour Default blue (#3b82f6). Used only when separate colours are enabled. Unavailable colour Default grey (#9ca3af). Used for drives whose activity cannot be measured. Use separate colours for Default OFF. See "Colours" in section 4. read-only / write-only Behaviour Update interval (ms) How often the counters are read. 50 to 2000. Default 150. Lower values make the LEDs blink more finely but use slightly more CPU. Minimum red time (ms) 0 to 1000. Default 80. How long an LED stays in its active colour after activity is seen. Ignore I/O below (KB/s) Default 0 (any I/O at all turns the LED red). Raise it to ignore low-level background activity that would otherwise keep a drive red. Max programs in tooltip 1 to 8. Default 3. Also count raw disk Default on. The raw-disk fallback described in activity (drive alone section 4. on its disk) Show drives that cannot Default on. Shows a grey LED, with an explanation be measured (grey LED) in its tooltip, for drives without activity data. Show total bytes read/ Default on. Total read and written in the tooltip. written in tooltip Show responsible programs Default on. The program list in the tooltip in tooltip (section 8). Show drive letters on LEDs Default on. Always on top Default on. On: the LEDs stay above all other windows. Off: the LEDs behave like an ordinary window and other windows can cover them. Takes effect immediately. Remember indicator Default on. Positions are saved when you drop an positions LED, when you press OK/Apply, and when the program exits, and are restored at the next start. When off, the LEDs start in the default layout every time. Save positions now Button: store the current positions immediately. Reset to default Button: forget saved positions and return the LEDs to the default layout. Lock position Default off. When on, LEDs cannot be dragged. Start with Windows Default off. Adds or removes a value named hdd_led under HKEY_CURRENT_USER\Software\Microsoft\Windows\ CurrentVersion\Run (no administrator rights needed). A Python script is started with pythonw.exe so that no console appears. Volumes to show One checkbox per detected drive. Untick a drive to hide its LED. 8. TOOLTIP CONTENTS ------------------- Example: D: Data Read: 12.4 MB/s Write: 310.0 KB/s IOPS: 188 Total read: 1.234 GB Total written: 56.78 MB (since 2026-10-14 09:30) Used: 120.3 GB of 465.8 GB (26%) Free: 345.5 GB Active programs (estimated): chrome 11.9 MB/s steam 410.0 KB/s Read / Write / IOPS Current rates for that drive. 1 KB = 1024 bytes. Source line Shown only when the data does not come from the normal volume counters: "SMB client share counters" for a network drive, or "physical disk N (raw access)" when the raw-disk fallback is in effect. Total read / Total written Bytes read from and written to the drive since the program started (or since "Reset totals"), shown with four significant digits, for example 1.234 GB, 56.78 MB, 123.4 KB, 1023 B. Units step up at 1024 (B, KB, MB, GB, TB, PB). The totals are obtained by adding up the measured rate over each update interval, so they are very close to - but not an exact audit of - the real byte count. They are kept in memory only, start from zero each time the program starts, and are kept for a drive even while it is temporarily unplugged. Used / Free Capacity information from Windows, refreshed every two seconds by the background scanner. Active programs (estimated) The programs (not individual processes) that most likely caused the drive's activity, with an estimated share of the speed. This is always the last block of the tooltip. Its height is fixed (one line per "Max programs in tooltip", padded with blank lines) and the tooltip uses a fixed-width font, so the lines above never move and the tooltip keeps the same size when programs appear or disappear. How it works. Windows does not give ordinary programs a counter that says "program X used drive D:" (an exact answer needs a kernel event trace, which requires administrator rights). hdd_led therefore estimates: 1. About every half second it reads each program's total I/O rate from the "Process" performance counters (IO Read Bytes/sec and IO Write Bytes/sec). Several processes with the same name, such as browser tabs, are added together. 2. It compares that with how much data each drive moved in the same period, and divides each drive's activity among the programs in proportion to their activity, never crediting a program with more than it actually did. 3. The result is smoothed, so the list follows what is happening now and fades away within a few seconds after the drive goes idle. Programs with less than a tenth of the leader's share are left out. The estimate is most reliable when one drive is busy at a time or one program clearly dominates. It can be wrong because the per-program counters also include non-disk I/O (network traffic, pipes), and because two drives busy at the same time cannot be perfectly told apart. A browser downloading a file may be listed for a drive that another program is actually using. Treat the list as a strong hint, not proof. To save CPU, the program counters are only read while at least one drive has been active within the last few seconds. If they cannot be read at all, the program list is omitted. If a drive cannot be measured at all, its tooltip shows the reason instead of these figures. 9. EXITING, AND CTRL-C ---------------------- Normal exit: right-click an LED and choose Exit. Console exit: when started with python.exe (or a console build of the exe), press Ctrl-C (or Ctrl-Break) in the console window. The program prints hdd_led: Ctrl-C received - saving settings and exiting cleanly... then saves its settings and LED positions, removes the LEDs, prints the session totals for every drive, and finishes with hdd_led: exited cleanly. Ctrl-C is handled on its own thread, so it works even when the rest of the program is busy or waiting for an unresponsive drive: * If the program has not finished shutting down within 3 seconds, it saves the settings and ends itself ("forcing exit"). * Pressing Ctrl-C a second time ends it immediately. Closing the console window with its X button, logging off and shutting down are handled the same way (settings are saved first). A termination request (SIGTERM) also exits cleanly. Under pythonw.exe or a --noconsole exe there is no console, so there is nothing to type Ctrl-C into; use the Exit menu item (or Task Manager). 10. FILES AND SETTINGS STORAGE ------------------------------ Settings file: %APPDATA%\hdd_led\config.json (normally C:\Users\\AppData\Roaming\hdd_led\) Error log: %APPDATA%\hdd_led\error.log Unexpected internal errors are written here with a traceback (there is no console under pythonw). A single failing drive or feature cannot stop the program; the affected part is skipped or switched off. The log is emptied when it passes 200 KB. Startup entry: HKCU\Software\Microsoft\Windows\CurrentVersion\Run, value "hdd_led" (only if "Start with Windows" is on) The settings file is plain JSON and can be edited while the program is NOT running. To restore all defaults, exit the program and delete config.json. Keys in config.json (default in brackets): size [28] LED diameter in pixels opacity [0.9] 0.2 to 1.0 idle_color [#22c55e] hex colour active_color [#ef4444] hex colour read_color [#f59e0b] hex colour write_color [#3b82f6] hex colour separate_rw [false] separate read-only / write-only colours shape ["circle"] "circle" or "square" show_letters [true] always_on_top [true] locked [false] remember_positions [true] poll_ms [150] update interval in milliseconds hold_ms [80] minimum time to stay in the active colour threshold_kbps [0.0] ignore I/O below this many KB/s use_physical_disk [true] raw-disk fallback show_unavailable [true] grey LED for drives that cannot be measured unavailable_color [#9ca3af] hex colour show_totals [true] show_processes [true] process_count [3] maximum programs listed per drive hidden [] hidden drives, e.g. ["E:"] positions {} saved positions, e.g. {"C:": [768, 0]} 11. DIAGNOSTICS WINDOW ---------------------- Right-click any LED and choose Diagnostics. The window updates twice a second and has a "Copy to clipboard" button, so its text can be pasted into a bug report. Header lines * Python version, update interval, minimum red time and the ignore threshold. * sampler: how many update ticks have run and how long ago the last one was. The count must keep rising. "errors" counts internal errors; "raw-disk counters" and "program counters" show whether those features are active. * volume scanner: what the background scanner is doing right now and for how many seconds. A long time on one drive means that drive is not responding. * last error: the most recent internal error, if any (details in error.log). One entry per drive Drive letter, type and label; where its data comes from (source) and the counter status; current read, write and IOPS; the totals; whether the raw-disk fallback is active, ready or not applicable; and the read/write rate of the physical disk(s) behind it (all volumes on that disk plus raw access). Read self-test Pick a drive in the "Read self-test on:" box and press Run. The program finds a file of at least 1 MB on that drive (preferably 64 MB or more; it searches for up to four seconds and skips system folders), reads up to 100 MB of it while bypassing the Windows file cache, then reports how much each counter recorded: PASS the volume counters saw the reads. The program works for this drive; reads by your own program that are not counted are most likely served from the Windows file cache (no disk access happens) or go to a different drive than you expect. PARTIAL only the physical-disk counters saw the reads (Windows does not attribute them to the volume). FAIL no counter saw the reads: Windows provides no read counters for this drive, or the counters are broken ("lodctr /R" run as administrator may repair them). The LED flashes while the test runs. The result stays at the top of the window, so "Copy to clipboard" includes it. The test only reads; it never changes anything on the drive. Other disk activity during the test is included in the figures. 12. TROUBLESHOOTING ------------------- No LEDs appear at all, or they appear late Once an LED shows, open Diagnostics and look at the "volume scanner" line; before that, check %APPDATA%\hdd_led\error.log. A long time on one drive (for example "finding the physical disk of E:" or "reading the free space of U:") means that drive is not answering; the program carries on without it. If the performance counters are damaged, no LEDs for local drives can be created: open a Command Prompt as administrator and run lodctr /R then start hdd_led again. LEDs never flash / totals stop growing / nothing updates Open Diagnostics and look at the "sampler" line: the tick count must keep rising and "last ... s ago" must stay under a second. "errors" and "last error" show internal problems; the full traceback is in error.log. Also check the "ignore below (KB/s)" and "min red time" values on the second line: a high threshold hides small I/O, and a very low red time makes flashes too brief to see. The LED only ever shows the active colour, never read-only / write-only Tick "Use separate colours for read-only / write-only" in Settings (it is off by default). If write-only activity looks the same as mixed activity, set the write-only colour to something different from the active colour. A drive shows no reads (or no activity at all) Run the read self-test (section 11), then look at that drive's entry: * status "OK", volume reads 0 B/s but the "physical disk" line shows reads: the reads bypass the file system (raw/sector access, imaging or benchmark tools) or belong to another volume on the same physical disk. If the drive is alone on its disk, the raw-disk fallback shows this automatically ("raw-disk assist: ACTIVE"); if the disk is shared by several lettered volumes the activity cannot be assigned to one of them. * both read 0 B/s: the data may be coming from the Windows file cache (no disk access happens), or the program doing the reading is reading from a different drive than you think. * status "counters returning no data" for more than a few seconds: the program rebuilds the counters by itself; if it persists, run "lodctr /R" as administrator. * source "none": Windows has no activity counters for that drive type (virtual or cloud drives, non-SMB network drives). An LED is red all the time Some drives always have low background activity. Raise "Ignore I/O below (KB/s)" in Settings (try 4 to 64). An LED disappeared It may have been hidden (Settings > Volumes to show), the drive was removed, or - for card readers and optical drives - there is no media in it. Empty card readers and drives without a disc are not listed. An LED is off-screen after changing monitors or resolution Right-click any LED > Reset positions. (Saved positions are also pulled back inside the current screen when the program starts.) The program list shows the wrong program See "Active programs" in section 8 - it is an estimate. Text looks blurry on a high-DPI display The program declares itself DPI-aware at start-up. If it still looks blurry, check the compatibility options of python.exe / the exe. Nothing happens on Ctrl-C Ctrl-C only works if the program was started in a console window (python.exe, not pythonw.exe). See section 9. It also works while the program is waiting for a stuck drive. 13. LIMITATIONS --------------- * Only drives with a drive letter are monitored. Network drives are measured only if they are SMB shares. * LEDs show activity per volume, not per physical disk. Two volumes on one physical disk can show different activity, and activity on one volume can slow the other. The raw-disk fallback only helps for a volume that is alone on its disk. * Rates and totals come from sampling (default every 150 ms); extremely short bursts between samples can be missed or averaged. * The program list is an estimate (section 8). * Positions are stored as screen coordinates and are not per-monitor aware. * Windows only; developed for Windows 10 and Windows 11.