Использование 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
Другие вопросы по тегам