[英]Error access to variable after try catch in PowerShell 7
我在 PowerShell 7 上收到此错误:
Total Urls to process: 12496
i: 1 | total:
RuntimeException:
Line |
45 | $percent = [int](100 * $i / $lines)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Attempted to divide by zero.
开发这个脚本:
$srcfile = "C:\Users\wnune\OneDrive\Escritorio\imagenes\cardlist.txt"
$urls = Get-Content $srcfile
$lines = 0
switch -File $srcfile { default { ++$lines } }
Write-Host "Total Urls to process: $lines "
$i = 0
Write-Progress -Activity "Downloading files" -Status "In progress" -PercentComplete $i;
$urls | ForEach-Object -Parallel {
$url = $_
try {
$filename = Split-Path $url -Leaf
$destination = "C:\Users\wnune\OneDrive\Escritorio\imagenes\$filename"
$ProgressPreference = 'SilentlyContinue'
$response = Invoke-WebRequest -Uri $url -ErrorAction SilentlyContinue
if ($response.StatusCode -ne 200) {
Write-Warning "============================================="
Write-Warning "Url $url return Error. "
continue
}
if (Test-Path $destination) {
Write-Warning "============================================="
Write-Warning "File Exist in Destination: $filename "
continue
}
$job = Start-BitsTransfer -Source $url -Destination $destination -Asynchronous
while (($job | Get-BitsTransfer).JobState -eq "Transferring" -or ($job | Get-BitsTransfer).JobState -eq "Connecting")
{
Start-Sleep -m 250
}
Switch(($job | Get-BitsTransfer).JobState)
{
"Transferred" {
Complete-BitsTransfer -BitsJob $job
}
"Error" {
$job | Format-List
}
}
}
catch
{
Write-Warning "============================================="
Write-Warning "There was an error Downloading"
Write-Warning "url: $url"
Write-Warning "file: $filename"
Write-Warning "Exception Message:"
Write-Warning "$($_.Exception.Message)"
}
$i++
Write-Host "i: $i | total: $lines"
$percent = [int](100 * $i / $lines)
Write-Progress -Activity "Downloading files" -Status "In progress" -PercentComplete $percent
}
Write-Progress -Activity "Downloading files" -Status "Completed" -Completed
假设这是因为我正在实施 -Parallel 尝试使用同步对象:
$syncObject = [System.Object]::new()
$srcfile = "C:\Users\wnune\OneDrive\Escritorio\imagenes\cardlist.txt"
$urls = Get-Content $srcfile
$lines = 0
switch -File $srcfile { default { ++$lines } }
Write-Host "Total Urls to process: $lines "
$i = 0
Write-Progress -Activity "Downloading files" -Status "In progress" -PercentComplete $i;
$urls | ForEach-Object -Parallel {
[System.Threading.Monitor]::Enter($syncObject)
try {
$url = $_
$filename = Split-Path $url -Leaf
$destination = "C:\Users\wnune\OneDrive\Escritorio\imagenes\$filename"
$ProgressPreference = 'SilentlyContinue'
$response = Invoke-WebRequest -Uri $url -ErrorAction SilentlyContinue
if ($response.StatusCode -ne 200) {
Write-Warning "============================================="
Write-Warning "Url $url return Error. "
continue
}
if (Test-Path $destination) {
Write-Warning "============================================="
Write-Warning "File Exist in Destination: $filename "
continue
}
$job = Start-BitsTransfer -Source $url -Destination $destination -Asynchronous
while (($job | Get-BitsTransfer).JobState -eq "Transferring" -or ($job | Get-BitsTransfer).JobState -eq "Connecting")
{
Start-Sleep -m 250
}
Switch(($job | Get-BitsTransfer).JobState)
{
"Transferred" {
Complete-BitsTransfer -BitsJob $job
}
"Error" {
$job | Format-List
}
}
}
catch
{
Write-Warning "============================================="
Write-Warning "There was an error Downloading"
Write-Warning "url: $url"
Write-Warning "file: $filename"
Write-Warning "Exception Message:"
Write-Warning "$($_.Exception.Message)"
}
finally
{
$i++
Write-Host "i: $i | total: $lines"
$percent = [int](100 * $i / $lines)
Write-Progress -Activity "Downloading files" -Status "In progress" -PercentComplete $percent
[System.Threading.Monitor]::Exit($syncObject)
}
}
Write-Progress -Activity "Downloading files" -Status "Completed" -Completed
得到另一个错误:
Total Urls to process: 12496
MethodInvocationException:
Line |
2 | [System.Threading.Monitor]::Enter($syncObject)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Exception calling "Enter" with "1" argument(s): "Value cannot be null."
如果我遵守执行顺序并且从头开始创建同步对象,我不知道出了什么问题或为什么会发生这种情况; 有人可以帮我弄这个吗???
主要思想是处理 12496 个 Urls... 并根据并行处理的 Urls 数量创建一个进度条。
这个提示不是这个的重复:
https://stackoverflow.com/a/60012780/20780615
注意:此答案不涵盖 PowerShell 工作流,因为它们是 PowerShell [Core] v6+ 不再支持的过时技术
阅读 First intead of Close Question。 并且与Invoke-Command
无关
PowerShell v7+ ForEach-Object
-Parallel
功能使用独立的、基于线程的运行空间来并行执行代码。
对于在运行空间外执行的任何 PowerShell 代码,您必须使用$using:
作用域来引用调用者作用域中的变量值。
$using
: 的所有上下文。一个简单的例子:
$i = 42
1..3 |
ForEach-Object -Parallel {
[pscustomobject] @{
'Thread-local $i' = $i
'$using:i value' = $using:i
}
}
输出:
Thread-local $i $using:i value
--------------- --------------
42
42
42
如您所见, $i
变量没有值,因为它引用了一个尚未初始化的线程局部(运行空间局部)变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.