更新
我不为这个错误而苦恼An event with the name 'StateChanged' does not exist
-请参阅下面的TRYOUTS(最后一个代码段)的完整代码
原始文本
如前所述,我正在执行一个代码,用于自动格式化文件并将文件传输到多个USB指驱动器。 并且它是并行/异步完成的
现在的问题是,我想在每个USB完成/工作完成时输出每个USB的驱动器号。该字母存储在job函数内部的var / param中,但是我不知道如何在完成工作后将其写出。
我有一个Register-ObjectEvent
,当每个USB格式化和传输完成后会触发。
该脚本运行得很好,并写出了USB slot = Job...
但是我想将$driveLetter
内部的$formatDrive
写在USB slot = $driveLetter
行中。
这里是我的代码。查找行$formatDrive
和$jobEvent
。
#Requires -version 2.0
ipmo storage
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange
$formatDrive = {
Param($driveLetter)
Write-Host (Get-Date -Format s) "Erase disk..."
$source = "C:\Users\myname\Desktop\test"
Format-Volume -DriveLetter $driveLetter[0] -NewFileSystemLabel "test30" -FileSystem exFAT -Confirm:$false
robocopy $source $driveLetter /S
return $driveLetter
}
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"}
}
if ($eventType -eq 2) {
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
Write-Host (Get-Date -Format s) "USB igang = " $driveLetter
# Execute process if drive matches specified condition(s)
$formatDrivejob = Start-Job -ScriptBlock $formatDrive -ArgumentList $driveLetter
$jobEvent = Register-ObjectEvent $formatDrivejob StateChanged -Action {
Write-Host (Get-Date -Format s) (' USB slot = Job #{0} ({1}) complete.' -f $sender.Id, $sender.Name)
[media.SystemSounds]::("Hand").Play()
$jobEvent | Unregister-Event
}
}
Remove-Event -SourceIdentifier volumeChange
} while (1-eq1) #Loop until next event
Unregister-Event -SourceIdentifier volumeChange
我尝试将其写在$formatDrive
的末尾-由于它在后台运行,因此无法正常工作。
您也可以在return
中看到$formatDrive
的尝试
试用:
#Requires -version 2.0
ipmo storage
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange
$formatDrive = {
param($driveLetter)
write-host (get-date -format s) "Erase disk..."
$source = "C:\Users\jbh\Desktop\test"
Format-Volume -Driveletter $driveLetter[0] -NewFileSystemLabel "test30" -FileSystem exFAT -Confirm:$false
robocopy $source $driveLetter /S
return $driveLetter
}
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"}
}
# initialize the array
$formatDrivejob = @()
if ($eventType -eq 2) {
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
Write-Host (Get-Date -Format s) "USB igang = " $driveLetter
# Execute process if drive matches specified condition(s)
$formatDrivejob += Start-Job -ScriptBlock $formatDrive -ArgumentList $driveLetter
$jobEvent = Register-ObjectEvent $formatDrivejob StateChanged -Action {
Write-Host (Get-Date -Format s) (' USB slot = Job #{0} ({1}) complete.' -f $sender.Id, $sender.Name)
[media.SystemSounds]::("Hand").Play()
foreach ($i in $formatDrivejob){
if ($i.State -eq "Completed")
{
$letter = $formatDrivejob | receive-job | select -Last 1
Write-Host "Drive has finished:" $letter
$formatDrivejob.Remove($i)
}
}
$jobEvent | Unregister-Event
}
}
Remove-Event -SourceIdentifier volumeChange
} while (1-eq1) #Loop until next event
Unregister-Event -SourceIdentifier volumeChange
答案 0 :(得分:1)
也许您可以尝试这样的方法:
$DrivesToHandle = 5
$formatDrivejob = @()
Do {
if ($eventType -eq 2) {
$DrivesToHandle -= 1
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
write-host (Get-Date -format s) "USB igang = $driveLetter"
# Execute process if drive matches specified condition(s)
$formatDrivejob += Start-Job -ScriptBlock $formatDrive -ArgumentList $driveLetter
}
} while ($DrivesToHandle -ne 0)
# Wait for all jobs to finish
$formatDrivejob | Wait-Job | Out-Null
# Retrieve the job results
$JobResults = $formatDrivejob | Receive-Job
foreach ($Job in $JobResults) {
Write-Host (get-date -format s) "Job result of job ID $($Job.Id): " $Job
}
# Remove all jobs
$formatDrivejob | Remove-Job -Force
使用jobs
时,可以使用Wait-Job
等待作业完成。但是您还必须通过使用Receive-Job
CmdLet来检索作业结果。
答案 1 :(得分:1)
您可以使用Receive-job
来获得结果:
# initialize the array
[System.Collections.ArrayList]$formatDrivejob
if ($eventType -eq 2) {
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
Write-Host (Get-Date -Format s) "USB igang = " $driveLetter
# Execute process if drive matches specified condition(s)
$formatDrivejob += Start-Job -ScriptBlock $formatDrive -ArgumentList $driveLetter
$jobEvent = Register-ObjectEvent $formatDrivejob StateChanged -Action {
Write-Host (Get-Date -Format s) (' USB slot = Job #{0} ({1}) complete.' -f $sender.Id, $sender.Name)
[media.SystemSounds]::("Hand").Play()
foreach ($i in $formatDrivejob){
if ($i.State -eq "Completed")
{
$letter = $formatDrivejob | receive-job | select -Last 1
Write-Host "Drive has finished:" $letter
$formatDrivejob.Remove($i)
}
}
$jobEvent | Unregister-Event
}
}