#Persistent
#SingleInstance Force
Menu, Tray, Icon, %A_WinDir%\System32\shell32.dll, 54
monitoring := true
alertedDrives := {}
spaceThreshold := 200
currentThreshold := "200 GB"
checkInterval := 300000
currentInterval := "5 Minutes"
; --- CONFIG ---
configDir := A_AppData "\HDD_Monitor_AHK"
configFile := configDir "\config.ini"
If !FileExist(configFile)
{
IniWrite, C:, %configFile%, Drives, Drive1
IniWrite, D:, %configFile%, Drives, Drive2
; Save defaults
IniWrite, 200, %configFile%, Settings, Threshold
IniWrite, 300000, %configFile%, Settings, Interval
}
; Load threshold
IniRead, spaceThreshold, %configFile%, Settings, Threshold, 200
if (spaceThreshold = 50)
currentThreshold := "50 GB"
else if (spaceThreshold = 100)
currentThreshold := "100 GB"
else if (spaceThreshold = 200)
currentThreshold := "200 GB"
else if (spaceThreshold = 500)
currentThreshold := "500 GB"
; Load interval
IniRead, checkInterval, %configFile%, Settings, Interval, 300000
if (checkInterval = 60000)
currentInterval := "1 Minute"
else if (checkInterval = 300000)
currentInterval := "5 Minutes"
else if (checkInterval = 600000)
currentInterval := "10 Minutes"
else if (checkInterval = 900000)
currentInterval := "15 Minutes"
else if (checkInterval = 1200000)
currentInterval := "20 Minutes"
else if (checkInterval = 1500000)
currentInterval := "25 Minutes"
else if (checkInterval = 1800000)
currentInterval := "30 Minutes"
else if (checkInterval = 3600000)
currentInterval := "1 Hour"
else if (checkInterval = 7200000)
currentInterval := "2 Hours"
else if (checkInterval = 18000000)
currentInterval := "5 Hours"
else if (checkInterval = 43200000)
currentInterval := "12 Hours"
; ---------------------------
; INTERVAL MENU
; ---------------------------
Menu, IntervalMenu, Add, 1 Minute, SetInterval
Menu, IntervalMenu, Add, 5 Minutes, SetInterval
Menu, IntervalMenu, Add, 10 Minutes, SetInterval
Menu, IntervalMenu, Add, 15 Minutes, SetInterval
Menu, IntervalMenu, Add, 20 Minutes, SetInterval
Menu, IntervalMenu, Add, 25 Minutes, SetInterval
Menu, IntervalMenu, Add, 30 Minutes, SetInterval
Menu, IntervalMenu, Add
Menu, IntervalMenu, Add, 1 Hour, SetInterval
Menu, IntervalMenu, Add, 2 Hours, SetInterval
Menu, IntervalMenu, Add, 5 Hours, SetInterval
Menu, IntervalMenu, Add, 12 Hours, SetInterval
; Default checkmark
Menu, IntervalMenu, Check, %currentInterval%
; ---------------------------
; THRESHOLD MENU
; ---------------------------
Menu, ThresholdMenu, Add, 50 GB, SetThreshold
Menu, ThresholdMenu, Add, 100 GB, SetThreshold
Menu, ThresholdMenu, Add, 200 GB, SetThreshold
Menu, ThresholdMenu, Add, 500 GB, SetThreshold
; Default checkmark
Menu, ThresholdMenu, Check, %currentThreshold%
; ---------------------------
; TRAY MENU
; ---------------------------
Menu, Tray, NoStandard
Menu, Tray, Add, Manage Monitored Drives, ManageDrives
Menu, Tray, Add, Pause Monitoring, ToggleMonitoring
Menu, Tray, Add
Menu, Tray, Add, Check Interval, :IntervalMenu
Menu, Tray, Add, Low Space Threshold, :ThresholdMenu
Menu, Tray, Add
Menu, Tray, Add, Exit, ExitApp
SetTimer, CheckSpace, %checkInterval%
return
; ---------------------------
; MAIN CHECK
; ---------------------------
CheckSpace(force := false)
{
global alertedDrives, spaceThreshold
drives := LoadDrives()
for index, drive in drives
{
; --- Get free space in KB ---
DriveSpaceFree, freeKB, %drive%
if ErrorLevel
continue ; skip if the drive doesn't exist
; --- Convert KB → GB and round ---
freeGB := Round(freeKB / 1024 / 1024, 1) ; 1 decimal place
; --- Check against threshold ---
if (freeGB <= spaceThreshold)
{
; Only alert once per drive unless forced
if (force || !alertedDrives.HasKey(drive))
{
alertedDrives[drive] := true
MsgBox, 48, Low Disk Space Warning, % "Drive " drive " has low free space:`n`n" freeGB " GB remaining (`< " spaceThreshold " GB threshold)."
}
}
else
{
; Reset alert if space is now above threshold
alertedDrives.Delete(drive)
}
}
}
; ---------------------------
; SET INTERVAL
; ---------------------------
SetInterval:
global checkInterval, monitoring, currentInterval
selected := A_ThisMenuItem
currentInterval := selected
; reset checkmarks
Menu, IntervalMenu, Uncheck, 1 Minute
Menu, IntervalMenu, Uncheck, 5 Minutes
Menu, IntervalMenu, Uncheck, 10 Minutes
Menu, IntervalMenu, Uncheck, 15 Minutes
Menu, IntervalMenu, Uncheck, 20 Minutes
Menu, IntervalMenu, Uncheck, 25 Minutes
Menu, IntervalMenu, Uncheck, 30 Minutes
Menu, IntervalMenu, Uncheck, 1 Hour
Menu, IntervalMenu, Uncheck, 2 Hours
Menu, IntervalMenu, Uncheck, 5 Hours
Menu, IntervalMenu, Uncheck, 12 Hours
Menu, IntervalMenu, Check, %selected%
; map interval
if (selected = "1 Minute")
checkInterval := 60000
else if (selected = "5 Minutes")
checkInterval := 300000
else if (selected = "10 Minutes")
checkInterval := 600000
else if (selected = "15 Minutes")
checkInterval := 900000
else if (selected = "20 Minutes")
checkInterval := 1200000
else if (selected = "25 Minutes")
checkInterval := 1500000
else if (selected = "30 Minutes")
checkInterval := 1800000
else if (selected = "1 Hour")
checkInterval := 3600000
else if (selected = "2 Hours")
checkInterval := 7200000
else if (selected = "5 Hours")
checkInterval := 18000000
else if (selected = "12 Hours")
checkInterval := 43200000
IniWrite, %checkInterval%, %configFile%, Settings, Interval
; restart timer only
if (monitoring)
{
SetTimer, CheckSpace, Off
SetTimer, CheckSpace, %checkInterval%
}
TrayTip, HDD Monitor, Interval set to %selected%, 3
return
; ---------------------------
; SET THRESHOLD
; ---------------------------
SetThreshold:
global spaceThreshold, currentThreshold
selected := A_ThisMenuItem
currentThreshold := selected
; clear checks
Menu, ThresholdMenu, Uncheck, 50 GB
Menu, ThresholdMenu, Uncheck, 100 GB
Menu, ThresholdMenu, Uncheck, 200 GB
Menu, ThresholdMenu, Uncheck, 500 GB
Menu, ThresholdMenu, Check, %selected%
if (selected = "50 GB")
spaceThreshold := 50
else if (selected = "100 GB")
spaceThreshold := 100
else if (selected = "200 GB")
spaceThreshold := 200
else if (selected = "500 GB")
spaceThreshold := 500
IniWrite, %spaceThreshold%, %configFile%, Settings, Threshold
TrayTip, HDD Monitor, Threshold set to %spaceThreshold% GB, 3
return
; ---------------------------
; LOAD DRIVES
; ---------------------------
LoadDrives() {
global configFile
drives := []
index := 1
Loop
{
IniRead, val, %configFile%, Drives, Drive%index%
if (val = "ERROR")
break
drives.Push(val)
index++
}
return drives
}
; ---------------------------
; MANAGE DRIVES GUI
; ---------------------------
ManageDrives:
Gui, Destroy
Gui, Add, Text,, Current monitored drives:
Gui, Add, ListBox, vDriveList w200 h120, % GetDriveListText()
Gui, Add, Button, gAddDrive w90, Add Drive
Gui, Add, Button, gRemoveDrive x+10 w90, Remove Drive
Gui, Add, Button, gCloseManage w90, Close
Gui, Show,, Manage Drives
return
GetDriveListText() {
drives := LoadDrives()
out := ""
for k, v in drives
out .= v "|"
return out
}
AddDrive:
InputBox, newDrive, Add Drive, Enter drive letter (e.g., E:)
if (ErrorLevel || newDrive = "")
return
StringUpper, newDrive, newDrive
global configFile
index := 1
Loop
{
IniRead, val, %configFile%, Drives, Drive%index%
if (val = "ERROR")
break
index++
}
IniWrite, %newDrive%, %configFile%, Drives, Drive%index%
GuiControl,, DriveList, % GetDriveListText()
return
RemoveDrive:
GuiControlGet, selected,, DriveList
if (selected = "")
return
global configFile
drives := LoadDrives()
FileDelete, %configFile%
index := 1
for k, v in drives
{
if (v != selected)
{
IniWrite, %v%, %configFile%, Drives, Drive%index%
index++
}
}
GuiControl,, DriveList, % GetDriveListText()
return
CloseManage:
Gui, Destroy
return
; ---------------------------
; PAUSE / RESUME MONITORING
; ---------------------------
ToggleMonitoring:
global monitoring, checkInterval
if (monitoring)
{
SetTimer, CheckSpace, Off
monitoring := false
Menu, Tray, Rename, Pause Monitoring, Resume Monitoring
}
else
{
SetTimer, CheckSpace, %checkInterval%
monitoring := true
Menu, Tray, Rename, Resume Monitoring, Pause Monitoring
}
return
; ---------------------------
; EXIT
; ---------------------------
ExitApp:
ExitApp