【问题标题】:ForEach loop in PowerShell failing after first iterationPowerShell 中的 ForEach 循环在第一次迭代后失败
【发布时间】:2016-08-11 18:03:26
【问题描述】:

我有一个数组 $Conventional,我需要每次循环并单击它,以便保存在 click() 之后可用的 PDF。

$Conventional = @()
$Conventional = $ie.Document.getElementsByTagName("td") | ? {($_.getAttributeNode('class').Value -match 'NodeDocument') -and ($_.innerText -notmatch 'Library Home')}

这用四个td 元素填充$Conventional,我每次都需要循环和click()。以下是我的 ForEach 循环,它在第一次迭代时运行良好,但是之后它每次都失败并返回 System.ComObject

ForEach ($i in $Conventional){

    $text = $i.innerText    

    $i.click()               
    while ($ie.Busy -eq $true){Start-Sleep -Seconds 2}

    $PDF = $ie.Document.getElementById("OurLibrary_LibTocUC_LandingPanel_libdocview1_DocViewDocMD1_hlViewDocument")

    $currentURL = $PDF.href
    $fileName = $baseFileName + "_" + $cleanText

    Invoke-WebRequest -Uri $currentURL -OutFile $NewPath\$fileName.pdf -WebSession $freedom
} 

这是我正在捕获的数组的屏幕截图。为了检索 PDF,需要单击每个 PDF。

任何帮助将不胜感激。谢谢大家

【问题讨论】:

  • foreach(){} 有时会遇到 COM 应用程序返回的集合的问题,因为它们没有正确实现 IEnumerable。尝试改用$Conventional |ForEach-Object { $_.InnerText }
  • 感谢您的回复,现在就试试吧!
  • 嗯,按照您建议的方式执行同样的问题。第一次迭代后,数组是空的,没有任何作用。当我删除 $_click() 它可以工作并打印 innerText 但我也需要它与 $_click() 一起工作。呜呜呜……
  • 不要使用@() 来实例化powershell 数组变量,而是使用带有= New-Object System.Collections.ArrayList 的.Net 数组,然后尝试添加到您的数组中。我不相信powershell会自动将$ie..getElementsById()的输出装箱,所以我会在powershell中工作以确保首先返回你的元素,然后如果它们被正确地转换到你的数组中,然后然后 确认元素格式正确后,在 foreach 循环中处理每个元素。
  • 好主意,谢谢。我将尝试实现这一点。

标签: arrays powershell foreach


【解决方案1】:

因为除非你按下点击它工作正常,那么也许点击事件会改变文档足以破坏你的$Conventional-array 中的元素引用。试试这个方法:

$linksToProcess = New-Object System.Collections.ArrayList

$ie.Document.getElementsByTagName("td") |
Where-Object {($_.getAttributeNode('class').Value -match 'NodeDocument') -and ($_.innerText -notmatch 'Library Home')} |
Foreach-Object { $linksToProcess.Add($_.innerText) }

while ($linksToProcess.Count -gt 0){

    $i = $ie.Document.getElementsByTagName("td") | ? {($_.getAttributeNode('class').Value -match 'NodeDocument') -and ($_.innerText -eq $linksToProcess[0])}

    $text = $i.innerText    

    $i.click()               
    while ($ie.Busy -eq $true){Start-Sleep -Seconds 2}

    $PDF = $ie.Document.getElementById("OurLibrary_LibTocUC_LandingPanel_libdocview1_DocViewDocMD1_hlViewDocument")

    $currentURL = $PDF.href
    $fileName = $baseFileName + "_" + $cleanText

    Invoke-WebRequest -Uri $currentURL -OutFile $NewPath\$fileName.pdf -WebSession $freedom

    $linksToProcess.RemoveAt(0)
}

【讨论】:

  • 感谢您的回复。我现在正在尝试。
  • 出于好奇,您是否有任何理由选择使用“while”循环并从数组中弹出值,而不是使用带计数器的 For 循环?
  • 没关系。我实际上会使用一个 foreach 循环,因为它只是一个字符串列表。 while 循环是从以前的想法中遗留下来的 :-)
最近更新 更多