完成后从作业输出参数



更新我没有遇到这个错误An event with the name 'StateChanged' does not exist-请参阅下面TRYOUT(最后一段代码(的完整代码


原始文本

如前所述,我正在编写一个代码,用于自动格式化文件并将其传输到多个USB拇指驱动器它是以并行/异步方式完成的

现在的问题是,我想在每个USB完成/作业完成时输出它们的驱动器号。这封信存储在job函数内的var/param中,但我不知道工作完成后如何写出它。

我有一个Register-ObjectEvent,当每个USB在格式化和传输中完成时就会触发。该脚本运行得非常好,并写出了USB slot = Job...

但我想把$formatDrive内部的$driveLetter写在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:UsersmynameDesktoptest"
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:UsersjbhDesktoptest"
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

您可以使用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
}
}

也许你可以尝试这样的方法:

$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-JobCmdLet来完成的。

最新更新