PowerShell磁盘信息采集脚本问题:USB接入重复显示所有磁盘信息
Got it, let's tackle this problem. The core issue with your current script is that when a USB arrives, you're pulling all disk drives via Get-WmiObject win32_diskdrive and looping through every single one—hence why you see all existing disks every time. Instead, we need to target only the device that triggered the arrival event.
Why This Happens
The Win32_VolumeChangeEvent already gives us the drive letter of the new device via its DriveName property. We can use that to trace back to the specific disk drive, partition, and serial number without scanning every connected drive.
Modified Script
Here's the adjusted version that only shows the newly inserted USB device, plus fixes the removal event logging (your original code had undefined variables there):
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange Write-Host (Get-Date -Format s) " Beginning script..." do { $newEvent = Wait-Event -SourceIdentifier volumeChange $eventDetails = $newEvent.SourceEventArgs.NewEvent $eventType = $eventDetails.EventType $eventTypeName = switch($eventType) { 1 {"Configuration changed"} 2 {"Device arrival"} 3 {"Device removal"} 4 {"Docking"} } Write-Host (Get-Date -Format s) " Event detected = $eventTypeName" if ($eventType -eq 2) { # Get the drive letter from the event (e.g., "D:") $targetDriveLetter = $eventDetails.DriveName if ($targetDriveLetter) { # Trace from the logical volume back to the disk drive $volume = Get-WmiObject -Class Win32_Volume | Where-Object { $_.Name -eq "$targetDriveLetter\" } if ($volume) { $partition = Get-WmiObject -Query "ASSOCIATORS OF {Win32_Volume.DeviceID=`"$($volume.DeviceID.Replace('\','\\'))`"} WHERE AssocClass = Win32_LogicalDiskToPartition" if ($partition) { $diskDrive = Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($partition.DeviceID.Replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition" if ($diskDrive) { # Display only the new USB device info Write-Host "`nNew USB Device Detected:" Write-Host "Device ID: $($diskDrive.DeviceID.Substring(4))" Write-Host "Model: $($diskDrive.Model)" Write-Host "Drive Letter: $targetDriveLetter" Write-Host "Serial Number: $($volume.SerialNumber)" # Log the event Write-EventLog -LogName Application -Source 'usb2.ps1' -EntryType Information -EventId 1 -Category 0 -Message "Date:$(Get-Date -Format s) Event detected:$eventTypeName Serial:$($volume.SerialNumber) Name:$($diskDrive.Model) Drive:$targetDriveLetter" } } } } } if ($eventType -eq 3) { # Get the drive letter being removed $removedDriveLetter = $eventDetails.DriveName if ($removedDriveLetter) { # Try to get last known info (or adjust if you need to track previously seen devices) $lastVolume = Get-WmiObject -Class Win32_Volume | Where-Object { $_.Name -eq "$removedDriveLetter\" } -ErrorAction SilentlyContinue $logMessage = if ($lastVolume) { "Date:$(Get-Date -Format s) Event detected:$eventTypeName Drive:$removedDriveLetter Serial:$($lastVolume.SerialNumber)" } else { "Date:$(Get-Date -Format s) Event detected:$eventTypeName Drive:$removedDriveLetter (No serial number found)" } Write-EventLog -LogName Application -Source 'usb2.ps1' -EntryType Information -EventId 1 -Category 0 -Message $logMessage } } Remove-Event -SourceIdentifier volumeChange } while ($true) # Loop until next event Unregister-Event -SourceIdentifier volumeChange
Key Improvements
- Targeted Querying: Instead of scanning all disks, we use the event's
DriveNameto trace directly to the new USB device, saving resources and avoiding duplicate output. - Fixed Removal Event: The original code tried to use
$serialand$drivevariables that weren't defined in the removal block—this version uses the event's drive letter to log relevant info. - Cleaner Output: Only the newly inserted device's details are displayed when an arrival event triggers.
Notes
- Make sure your script has permission to write to the Application event log (you might need to run PowerShell as Administrator).
- If you need to track multiple USB devices over time, you could add a variable to store previously seen devices, but for the core request of showing only the new device on arrival, this should work perfectly.
内容的提问来源于stack exchange,提问作者Sovakah

