Small app/script that will warn if an (external) drive is not connected


eulenfalter

Active member
Local time
10:02 AM
Posts
18
OS
Windows 11 Pro ARM64 (Apple Silicon M1/Parallels)
Hello,

I'd like to be informed (either immediately or with a delay of at max 10 minutes) if drive H: is not available/connected.

ChatGPT said I should schedule this .bat file in Task scheduler, but I have no clue if this is safe or has issues:

Code:
@echo off

set DriveLetter=H:
set FlagFile=%TEMP%\DriveNotConnected.flag

if not exist %DriveLetter%\ (
    if not exist %FlagFile% (
        msg * "Drive %DriveLetter% not connected!"
        echo. > %FlagFile%
    )
) else (
    del %FlagFile% 2>nul
)

Do you have any suggestions for a ready-made app, or suggestions how to improve the above ChatGPT-code in case it has bugs/issues?

Thank you very much.
 

My Computer

System One

  • OS
    Windows 11 Pro ARM64 (Apple Silicon M1/Parallels)
    Computer type
    Laptop
    Manufacturer/Model
    Apple
    CPU
    M1 Apple Silicon
    Memory
    5 GB VM / 16 GB Host (MacOS)
    Monitor(s) Displays
    13.3" retina
    Hard Drives
    1 TB SSD
    Mouse
    touchpad (internal)

here you may find something that actually works.
 

My Computer

System One

  • OS
    Windows 11 Pro ARM64 (Apple Silicon M1/Parallels)
    Computer type
    Laptop
    Manufacturer/Model
    Apple
    CPU
    M1 Apple Silicon
    Memory
    5 GB VM / 16 GB Host (MacOS)
    Monitor(s) Displays
    13.3" retina
    Hard Drives
    1 TB SSD
    Mouse
    touchpad (internal)
You can always use powershell, a simple example:

DriveWatcher.ps1
Powershell:
while($true){
while (Test-Path -Path H:\) {sleep 2}
Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('Drive disconnected, please plug the drive back in.')
sleep 2
}

This will tell you to plug the drive back in when it is disconnected forever until you do using speech synthesizer ;P
 

My Computer

System One

  • OS
    PE
Are you still interested?
Can you guarantee that the drive will always be H:\?
Would you be happy to give the drive a label as that is permanent and can be searched for?

I do not set fixed drive letters for any of my external drives. I give them labels and run a script to find them - the script either returns "not connected" or whatever the drive letter happens to be that time.


Denis
 

My Computer

System One

  • OS
    Windows 11 Home x64 Version 22H2 Build 22631.3155
To add to what @Try3 said, if programs are not installed onto a removable drive [and shouldn't be] the drive doesn't need a static letter but it would be helpful to have a unique label showing in File Explorer or other file manager, such as its capacity, USB16GB-1, or a name, M#1of93, etc.
 

My Computers

System One System Two

  • OS
    Win11 Pro RTM
    Computer type
    Laptop
    Manufacturer/Model
    Dell Vostro 3400
    CPU
    Intel Core i5 11th Gen. 2.40GHz
    Memory
    12GB
    Hard Drives
    256GB SSD NVMe
  • Operating System
    Windows 11 Pro RTM x64
    Computer type
    PC/Desktop
    Manufacturer/Model
    Dell Vostro 5890
    CPU
    Intel Core i5 10th Gen. 2.90GHz
    Memory
    16GB
    Graphics card(s)
    Onboard, no VGA, using a DisplayPort-to-VGA adapter
    Monitor(s) Displays
    24" Dell
    Hard Drives
    512GB SSD NVMe, 2TB WDC HDD
    Browser
    Firefox, Edge
    Antivirus
    Windows Defender/Microsoft Security
Here's a way to monitor USB drive disconnects, using your drive's unique DeviceID, based on the Vendor & Model & Serial Number.

1 First, run this PowerShell script to determine your USB drive's DeviceID:
Code:
@(gwmi Win32_PnPEntity | ?{ $_.DeviceID -match '^USBSTOR' } | %{
    $DeviceID = $_.DeviceID
    [PSCustomObject]@{
        Drive = gwmi Win32_DiskDrive | ?{ $_.PNPDeviceID -eq $DeviceID } | %{ Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition" } `
            | %{ Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.DeviceID}
        Model = $_.Name
        DeviceID = $DeviceID
    }
}) | Sort-Object Drive

I have replaced my drives' actual S/N with randomized output.
Code:
Drive Model                             DeviceID                                                              
----- -----                             --------                                                              
D:    Corsair Voyager USB Device        USBSTOR\DISK&VEN_CORSAIR&PROD_VOYAGER&REV_0.00\444444444444444Q&4     
E:    Seagate Expansion Desk USB Device USBSTOR\DISK&VEN_SEAGATE&PROD_EXPANSION_DESK&REV_9401\UU1UUU11&1      
F:    Seagate Portable USB Device       USBSTOR\DISK&VEN_SEAGATE&PROD_PORTABLE&REV_0712\FF00FFFF&0            
G:    Seagate Backup+  Desk USB Device  USBSTOR\DISK&VEN_SEAGATE&PROD_BACKUP+__DESK&REV_0406\QQ4QQ444&4       
R:    Seagate Backup+ Hub BK USB Device USBSTOR\DISK&VEN_SEAGATE&PROD_BACKUP+_HUB_BK&REV_D781\RR3RR33R&3      
S:    Seagate Expansion Desk USB Device USBSTOR\DISK&VEN_SEAGATE&PROD_EXPANSION_DESK&REV_0915\GGGGGGGG&0      
T:    Seagate Expansion HDD USB Device  USBSTOR\DISK&VEN_SEAGATE&PROD_EXPANSION_HDD&REV_0003\66666666QQQ6Q6Q6&6

2. Pick your desired USB device:
D:\ which is my Corsair Voyager flash drive, it can be identified as "USBSTOR*CORSAIR*VOYAGER*" using wildcards.​
G:\ which is one of many Seagate HDD's, can be identified as "USBSTOR*SEAGATE*QQ4QQ444*" (where QQ4QQ444 is the unique S/N).​

3. Edit this script and replace the $DeviceID (using wildcards)
Code:
# https://stackoverflow.com/questions/54482594/powershell-wmi-trigger-action-when-specific-device-is-plugged-in

# Use '%' for wildcard
$DeviceID = 'USBSTOR%CORSAIR%VOYAGER%'

Unregister-Event -SourceIdentifier USBDisconnected -ErrorAction Ignore

# Event when disconnected (InstanceDeletionEvent)
$Disconnect_Action = {
    msg * Corsair Voyager has been unplugged.
}

$query = "Select * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PNPEntity' and TargetInstance.DeviceID like '$DeviceID'"
Register-WMIEvent -Query $query -Action $Disconnect_Action -SourceIdentifier USBDisconnected

4. Write the script to USB_Disconnect.ps1, and then run as Administrator:
Code:
powershell -nop -ep bypass -f USB_Disconnect.ps1

After my Corsair Voyager is unplugged, then a registered task will be executed. In this case, a message pops onscreen. You can replace the command inside $Disconnect_Action with whatever external command you want. If you have multiple drives to monitor, create parallel Register-WMIEvent's with a different -SourceIdentifier name. Running an event trigger is more efficient than scheduling a repeated task every few minutes, or running a constant polling loop.

For more background, you can read this previous thread:
 

My Computer

System One

  • OS
    Windows 7
Another excellent garlin tool.

My own assumes that a drive label has been assigned and uses that to search on. I use it, for example, to find the correct disks in my backup scripts since drive labels never get lost.
GetDriveLetter-SubRoutine - my post #5 - ElevenForum


All the best,
Denis
 

My Computer

System One

  • OS
    Windows 11 Home x64 Version 22H2 Build 22631.3155
Hello! Thank you all for thinking of and developing solutions!
I was able to use some rudimentary makeshift construction (as I can't code, just mess with scripts and beg ChatGPT to come up with solutions (which do work half of the time). What I'm about to write now will hurt the eyes of anybody who can code. Trigger warning.

So, I have Windows task scheduler run a vbs script every 10 minutes.

Drive_Check.vbs does this:

Code:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "cmd /c C:\Admin\Backup\Drive_Check\Drive_Check.bat", 0
Set objShell = Nothing

The bat then does this:

Code:
@echo off

set DriveLetter=H:
set FlagFile=C:\Admin\Backup\Drive_Check\DriveNotConnectedDoNotWarnAgain.flag
set "nircmdPath=C:\Admin\Backup\Drive_Check\nircmd.exe"

if not exist %DriveLetter%\ (
    if not exist %FlagFile% (
        start "Drive Checker" "%nircmdPath%" infobox "Please connect flash drive! :-)" "Drive Checker" 0 0
        echo. > %FlagFile%
    )
) else (
    if exist %FlagFile% (
        del %FlagFile%
    )
)

Plus, windows task scheduler also runs this vbs every 30 minutes:

Code:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "cmd /c C:\Admin\Backup\Drive_Check\FlagFileRemover.bat", 0
Set objShell = Nothing

the bat being:
Code:
@echo off

set FlagFile=C:\Admin\Backup\Drive_Check\DriveNotConnectedDoNotWarnAgain.flag

if exist %FlagFile% (
    del %FlagFile% >nul 2>&1
)

This has been working very reliably, the only problem being that it will amass warnings if the
computer has been runnning whilst I was not using it. It's not a big deal though, I can close the warnings fast.
Another thing is, I would have preferred the warnings to show without grabbing focus, i.e. they should
show on top of screen and remain there until closed, but not grab focus. But this has not been a significant
issue so far either.

About your questions: it is not problem if a program/script requires the USB drive to have a specific label, and will
only work for that drive (or even for a list of defined labels, warning if any of them is not accessible). Also a
check frequency of 10 minutes suffices. Instead of a label, it would also be OK if the program checks for
the presence of a specific file on a drive, such as: check if file "567873867.info" is presend in the root of R: , or some
subfolder.

My initial thought was primarily that it would be nice if such a program existed that would warn if a drive
is not connected, not as a script or anything that's difficult for average users to set up, but as a nice
interface program that everybody can install like a small program and use with no manual (and no brains, fool-proof).

I think it's imporant to note that the usage scenarios are limited to
- scatterbrained people that for some reason need to make sure a drive is connected, or NOT connected (e.g. for security reasons)
- backup context: making sure people do their backups / that the backup works, as an additional layer of protection
- in my case, it's because Parallels Desktop loses connection to USB drives once in a while, and I do backups to that drive, and I don't like the specific warnings of the backup program / they don't work so reliably.

The above makeshift stuff has warned me a dozen times since my initial posting, and reliably so.

I must say though, what would also help is a service checker: If I were warned if a certain service was not running, if this
has been the case for longer than e.g. 30-60 minutes or so. (would not have to be an exact time, could vary). In general
I like the idea of programs that check other programs/stuff if everything is working properly. Such as "is window X / program
Y running" - If not, warn. Because human error is one of the main causes of data loss.
 

My Computer

System One

  • OS
    Windows 11 Pro ARM64 (Apple Silicon M1/Parallels)
    Computer type
    Laptop
    Manufacturer/Model
    Apple
    CPU
    M1 Apple Silicon
    Memory
    5 GB VM / 16 GB Host (MacOS)
    Monitor(s) Displays
    13.3" retina
    Hard Drives
    1 TB SSD
    Mouse
    touchpad (internal)
Just a side note... VBScript (used in @eulenfalter's solution) and the WMI cmdlets (used in @garlin's solution) are both deprecated.

VBScript : Deprecated features in the Windows client - What's new in Windows

Get-WmiObject and Register-WmiEvent were deprecated in PowerShell 3, in favor of Get-CimInstance and Register-CimIndicationEvent, respectively. In fact, the WMI versions don't even exist in current PowerShell versions, only in Windows PowerShell.
 

My Computers

System One System Two

  • OS
    Windows 11 Pro 22H2 [22621.3155]
    Computer type
    PC/Desktop
    Manufacturer/Model
    Intel NUC12WSHi7
    CPU
    12th Gen Intel Core i7-1260P, 2100 MHz
    Motherboard
    NUC12WSBi7
    Memory
    64 GB
    Graphics Card(s)
    Intel Iris Xe
    Sound Card
    built-in Realtek HD audio
    Monitor(s) Displays
    Dell U3219Q
    Screen Resolution
    3840x2160 @ 60Hz
    Hard Drives
    Samsung SSD 990 PRO 1TB
    Keyboard
    CODE 104-Key Mechanical Keyboard with Cherry MX Clears
  • Operating System
    Linux Mint 21.2 (Cinnamon)
    Computer type
    PC/Desktop
    Manufacturer/Model
    Intel NUC8i5BEH
    CPU
    Intel Core i5-8259U CPU @ 2.30GHz
    Memory
    32 GB
    Graphics card(s)
    Iris Plus 655
    Keyboard
    CODE 104-Key Mechanical Keyboard - Cherry MX Clear
indeed, thank you. it says: oct 2023: "VBScript VBScript is deprecated. In future releases of Windows, VBScript will be available as a feature on demand before its removal from the operating system. For more information, see Resources for deprecated features."

It's interesting that initially I was told that all of this is such a trivial and easy matter, nobody would every think of making a small program for this, but now it turns out to be not quite as straightforward....

I've been wondering if there is some software that is relatively powerful and that can, among many other things, also perform the checks that I mentioned. (No, not AutoHotKey, I mean a full UI program with visualized algorithms, usable for anybody withouth programming skills. Perhaps similar to MacOS shortcuts. But then again that's overkill. I think last time I checked, there was such a program (forgot the name), but it was quite expensive.
 

My Computer

System One

  • OS
    Windows 11 Pro ARM64 (Apple Silicon M1/Parallels)
    Computer type
    Laptop
    Manufacturer/Model
    Apple
    CPU
    M1 Apple Silicon
    Memory
    5 GB VM / 16 GB Host (MacOS)
    Monitor(s) Displays
    13.3" retina
    Hard Drives
    1 TB SSD
    Mouse
    touchpad (internal)
I actually made this many moons ago, for our computer labs. Its purpose was to remind people to grab their flash drives when they logged out of Windows. We stopped using it when USB drives became much less popular on our campus. It could be extended to serve as a reminder app, like you're talking about.

1708743031242.png
 

My Computers

System One System Two

  • OS
    Windows 11 Pro 22H2 [22621.3155]
    Computer type
    PC/Desktop
    Manufacturer/Model
    Intel NUC12WSHi7
    CPU
    12th Gen Intel Core i7-1260P, 2100 MHz
    Motherboard
    NUC12WSBi7
    Memory
    64 GB
    Graphics Card(s)
    Intel Iris Xe
    Sound Card
    built-in Realtek HD audio
    Monitor(s) Displays
    Dell U3219Q
    Screen Resolution
    3840x2160 @ 60Hz
    Hard Drives
    Samsung SSD 990 PRO 1TB
    Keyboard
    CODE 104-Key Mechanical Keyboard with Cherry MX Clears
  • Operating System
    Linux Mint 21.2 (Cinnamon)
    Computer type
    PC/Desktop
    Manufacturer/Model
    Intel NUC8i5BEH
    CPU
    Intel Core i5-8259U CPU @ 2.30GHz
    Memory
    32 GB
    Graphics card(s)
    Iris Plus 655
    Keyboard
    CODE 104-Key Mechanical Keyboard - Cherry MX Clear
Just a side note... VBScript (used in @eulenfalter's solution) and the WMI cmdlets (used in @garlin's solution) are both deprecated.

VBScript : Deprecated features in the Windows client - What's new in Windows

Get-WmiObject and Register-WmiEvent were deprecated in PowerShell 3, in favor of Get-CimInstance and Register-CimIndicationEvent, respectively. In fact, the WMI versions don't even exist in current PowerShell versions, only in Windows PowerShell.
I hear you, but I write all my PowerShell scripts in PS 5.1 for backwards compatibility. Too old to care about migrating to PS 6+.

When that day arrives, I'll allow someone else to answer all these questions. :what:
 

My Computer

System One

  • OS
    Windows 7
I hear you, but I write all my PowerShell scripts in PS 5.1 for backwards compatibility. Too old to care about migrating to PS 6+.

When that day arrives, I'll allow someone else to answer all these questions. :what:

The wmi cmdlets are replaced by cmi cmdlets. It should be fairly straightforward to migrate the script to use cim instead.
 

My Computers

System One System Two

  • OS
    Windows 11 Pro x64
    Computer type
    PC/Desktop
    Manufacturer/Model
    DIY Photoshop/Game/tinker build
    CPU
    10900K, 5.2 GHz all cores
    Motherboard
    Asus ROG Maximus Hero XIII Wifi
    Memory
    64GB (2x32) G.skill TridentZ RGB 4266 MHz (Hynix) @ 18-24-24-42
    Graphics Card(s)
    Asus ROG Strix 4070 Ti OC
    Sound Card
    Onboard Audio, Vanatoo Transparent One; Klipsch R-12SWi Sub; Creative Pebble Pro Minimilist
    Monitor(s) Displays
    Eizo CG2730, ViewSonic VP2768
    Screen Resolution
    2560 x 1440p x 2
    Hard Drives
    WDC SN850 1TB nvme, SK-Hynix 2 TB P41 nvme, Raid 0: 1TB 850 EVO + 1TB 860 EVO SSD. Sabrent USB-C DS-SC5B 5-bay docking station: 6TB WDC Black, 6TB Ironwolf Pro; 2x 2TB WDC Black
    PSU
    850W Seasonic Vertex PX-850
    Case
    Fractal Design Meshify 2 dark tint glass
    Cooling
    EKWB 360 Nucleus Dark AIO w/Phanteks T30-120 fans, 1 Noctua NF-A14 Chromax case fan
    Keyboard
    Glorious GMMK TKL mechanical, lubed modded
    Mouse
    Logitech G305 wireless gaming
    Internet Speed
    380 Mb/s down, 12 Mb/s up
    Browser
    Firefox
    Antivirus
    Defender, Macrium Reflect 8 ;-)
  • Operating System
    Mac OS
    Computer type
    Laptop
    Manufacturer/Model
    Apple 13" Macbook Pro 2020 (m1)
    CPU
    Apple M1
    Screen Resolution
    2560x1600
    Browser
    Firefox
The wmi cmdlets are replaced by cmi cmdlets. It should be fairly straightforward to migrate the script to use cim instead.

Great. You want to help convert this code block?
Code:
Get-WmiObject Win32_DiskDrive | ?{ $_.PNPDeviceID -eq $DeviceID } | %{ Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition" } `
            | %{ Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.DeviceID}
 

My Computer

System One

  • OS
    Windows 7

Latest Tutorials

Back
Top Bottom