#list #powershell #search #word
#Список #powershell #Поиск #слово
Вопрос:
Я нашел некоторый код для поиска строк в документе Word. Я изменил его в соответствии со своими потребностями (мне нужно выполнить поиск по очень длинному списку строк). К сожалению, я получаю странную ошибку.
Во время выполнения сценария он открывает документ word, выполняет поиск в документе word, и вот тут становится странно, вместо того, чтобы закрыть документ и открыть следующий, он представляет мне диалоговое окно «сохранить как», и сценарий зависает, пока я не отменю его. Когда я отменяю его, мой сценарий продолжается.
Вот сценарий, который я использую, кто-нибудь увидит, куда я направляюсь на юг?
$results = @{} Write-Host "Loading getStringMatch into memory" -ForegroundColor DarkMagenta Function getStringMatch { # Loop through all *.doc files in the $path directory Foreach ($file In $files) { Write-Host "Searching In ... $($File.FullName) " -ForegroundColor DarkYellow $document = $application.documents.open($file.FullName,$false,$true) $range = $document.content If($range.Text -match ".{$($charactersAround)}$($findtext).{$($charactersAround)}"){ $properties = @{ File = $file.FullName Match = $findtext TextAround = $Matches[0] } $results = @(New-Object -TypeName PsCustomObject -Property $properties) } $document.close() Write-Host "Closing Document ... $($File.FullName) " -ForegroundColor Red } #If($results){ # $results | Export-Csv $output -NoTypeInformation #} $application.quit() } $searchWords=Get-Content "C:TempUSDA_Search_For.txt" Foreach ($sw in $searchWords) { Write-Host "Setting Variables ..." -ForegroundColor DarkMagenta Set-StrictMode -Version latest $path = "C:Temp" $files = Get-Childitem $path -Include *.docx,*.doc -Recurse | Where-Object { !($_.psiscontainer) } $output = "C:TempFound.csv" $application = New-Object -comobject word.application $application.visible = $False $findtext = "First" $charactersAround = 30 #$results = @{} $findtext = $sw Write-Host "Searching For ... $findtext" -ForegroundColor Green getStringMatch #clean up stuff [System.Runtime.InteropServices.Marshal]::ReleaseComObject($application) | Out-Null Remove-Variable -Name application [gc]::collect() [gc]::WaitForPendingFinalizers() } If($results){ $results | Export-Csv $output -NoTypeInformation } import-csv $output
Комментарии:
1. Получаете ли вы запрос на подтверждение до или после вывода на экран «Закрытие документа … lt;путь к файлуgt;»? Если раньше, попробуйте перейти
$document.close()
на$document.Close($false)
2.Кроме того, определите приведенный
$application = New-Object -comobject word.application
выше цикл foreach (только один раз). Удалите$application.quit()
изgetStringMatch
функции и переместите ее ниже цикла foreach. После этого выполните очистку, чтобы освободить COM-объекты из памяти3. @MathiasR.Jessen и Тео, это сработало!! Спасибо вам обоим. У меня есть еще один вопрос, если можно. Я думаю, что, возможно, я неправильно закодировал это. Я открываю и закрываю более 100 документов Word для каждой строки, которую ищу. Есть ли способ изменить приведенный выше код, чтобы открыть каждый документ Word только один раз и выполнить поиск по каждой строке, а затем перейти к следующему документу Word? Причина, по которой я спрашиваю, заключается в том, что моя тестовая папка с 25 документами и более чем 150 строками для поиска занимает более 5 минут.
4. Вы могли бы объединить все
$searchWords
с регулярным выражением ИЛИ|
так, чтобы вам вообще не нужно было их зацикливать..$searchWords= '({0})' -f ((Get-Content "C:TempUSDA_Search_For.txt | ForEach-Object { [regex]::Escape($_) }) -join '|')
5. @Тео, Это сработало Очаровательно!!! Сейчас он быстро разгорается. Большое спасибо!!