Использование PowerShell для запуска командного файла для безопасного стирания USB-накопителя
Я использую PowerShell для запуска bat-файла, который стирает подключенный USB-накопитель. Если я использую сценарий без Start-Process
он работает нормально, но я хочу подключить несколько дисков и стереть их одновременно.
Сценарий:
Register-WmiEvent -Class Win32_VolumeChangeEvent -SourceIdentifier VolumeChange
Write-Host (Get-Date -Format s) " Beginning script..."
do {
$newEvent = Wait-Event -SourceIdentifier volumeChange
$eventType = $newEvent.SourceEventArgs.NewEvent.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) {
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
Write-Host (Get-Date -Format s) " Drive name = " $driveLetter
Write-Host (Get-Date -Format s) " Drive label = " $driveLabel
# Execute process if drive matches specified condition(s)
if ($driveLabel -eq 'BBIFREE_01' -or $drivelabel -eq 'HD10') {
Write-Host (Get-Date -Format s) " Starting task in 3 seconds..."
Start-Sleep -Seconds 3
Start-Process -FilePath D:\wipe.bat $driveLetter, $driveLabel
Copy-Item -Path D:\Utilities1 -Destination $driveLetter -Recurse
$driveEject = New-Object -ComObject Shell.Application
$driveEject.Namespace(17).ParseName($driveLetter).InvokeVerb("Eject")
}
}
Remove-Event -SourceIdentifier VolumeChange
} while (1 -eq 1) #Loop until next event
Unregister-Event -SourceIdentifier VolumeChange
Содержимое файла bat:
set arg1=%1
set arg2=%2
format %args1% /FS:NTFS /p:1 /V:%args2% /x /y
РЕДАКТИРОВАТЬ
Для пояснения: сценарий должен непрерывно запускаться на определенном ПК, где он должен запускать файл bat (как в случае безопасного стирания диска) каждый раз, когда обнаруживает подключенный диск. Если я использую:
D:\wipe.bat -ArgumentList `"$driveLetter",`"$driveLabel"
затем он начинает стирание на 1 диске и только на 1 диске.
Мне нужно, чтобы обнаружить несколько дисков, поэтому я использовал Start-Process
видя, как я думал, он будет работать на заднем плане и продолжать следить за новыми событиями.
EDIT2
Я изменил код, чтобы избежать использования -ArgumentList
см. выше.
Если я поставлю echo
Команда в моем командном файле в соответствии с просьбой:
set arg1=E:
set arg2=BBIFREE_01
ECHO ECHO IS ON
ECHO ECHO IS ON
Поэтому я вижу команды в файле bat, но он не выполняется и идет прямо к команде копирования.
1 ответ
Это слегка измененная версия скрипта, который я написал некоторое время назад, у меня нет времени, чтобы подтвердить, что он работает на 100%, но он должен, по крайней мере, направить вас в правильном направлении, он просто наматывает фактическое стирание, чтобы он мог обрабатывать другие задания в фоновом режиме, а затем использовать глобальное всплывающее окно, чтобы предупредить о его завершении, чтобы предотвратить необходимость блокировки во время завершения задания.
Должен быть в состоянии обрабатывать любое количество устройств одновременно, он использует PowerShell Format-Volume
вместо этого, но вместо этого вы можете поместить вызов файла BAT в задание.
$USBWhiteList = @( #Add wildcard items here, if a USB matches one it will be wiped.
"USB0*"
"*WIPE"
)
Enum EventNames{ Changed = 1 ; Inserted = 2 ; Removed = 3 ; Docking = 4 } #Names for events
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange -ErrorAction SilentlyContinue #register the event
do{
Write-Host "Monitoring for Disk events..." -Fore Yellow
$Event = Wait-Event -SourceIdentifier volumeChange #wait for a disk event
$EventType = [EventNames]$Event.SourceEventArgs.NewEvent.EventType #get the type of the event
Write-Host "Drive $($EventType), Processing..." -Fore Yellow -NoNewline
$Volume = Get-Volume -DriveLetter $Event.SourceEventArgs.NewEvent.DriveName -ErrorAction SilentlyContinue #get the volume details
$IsMatch = ($USBWhiteList|? {$Volume.FileSystemLabel -like $_}).Count -gt 0 #does it match our whitelist?
if (($EventType -eq [EventNames]::Inserted) -and $IsMatch){ #if a disk was inserted which matches the whitelist...
Write-Host "Volume $($Volume.DriveLetter): '$($Volume.FileSystemLabel)', Found, Wiping!" -Fore Green
Start-Job -ScriptBlock { param ($Volume) #Perform the wipe inside a job
$Disk = Get-Partition -DriveLetter $Volume.DriveLetter | Get-Disk
Clear-Disk -Number $Disk.Number -RemoveData -Confirm:$false
New-Partition -DiskNumber $Disk.Number -UseMaximumSize -IsActive -DriveLetter $Volume.DriveLetter
Format-Volume -FileSystem NTFS -DriveLetter $Volume.DriveLetter -Confirm:$false
Add-Type -AssemblyName 'System.Windows.Forms' #warn (globally) when it is finished, don't need to run wait/recieve job.
[System.Windows.Forms.MessageBox]::Show("Finished Wiping Disk $($Volume.DriveLetter)","Please Remove Disk")
} -ArgumentList $Volume | Out-Null
} else {
Write-Host "Ignoring" -Fore Red
}
Remove-Event -SourceIdentifier volumeChange
} while (1) #this should be modified to quit after x disks or something, the below commands won't get exec'd - could also use a Try/Finally and Ctrl+C the script.
Get-Job | Remove-Job -Force
Unregister-Event -SourceIdentifier volumeChange