1

我有一個將Office文檔轉換爲PDF的Powershell腳本。我想多線程,但無法根據我見過的其他例子來弄清楚。主腳本(OfficeToPDF.ps1)掃描文件列表,併爲每個文件類型/辦公應用程序調用單獨的腳本(例如調用WordToPDF.ps1以轉換)。主腳本一次將1個文件名傳遞給子腳本(出於幾個原因,我這樣做了)。Powershell多線程

這裏是主腳本的一個示例:

$documents_path = "C:\Documents\Test_Docs" 
    $pdf_out_path = "C:\Documents\Converted_PDFs" 
    $failed_path = "C:\Documents\Failed_to_Convert" 

    # Sets the root directory of this script 
    $PSScriptRoot = Split-Path -parent $MyInvocation.MyCommand.Definition 

    $date = Get-Date -Format "MM_dd_yyyy" 
    $Logfile = "$PSScriptRoot\logs\OfficeToTiff_$Date.log" 

    $word2PDF = "$PSScriptRoot\WordToPDF.ps1" 
    $arguments = "'$documents_path'", "'$pdf_out_path'", "'$Logfile'" 

    # Function to write to log file 
    Function LogWrite 
    { 
     Param ([string]$logstring) 
     $time = Get-Date -Format "hh:mm:ss:fff" 

     Add-content $Logfile -value "$date $time $logstring" 
    } 


################################################################################ 
# Word to PDF                 # 
################################################################################ 

    LogWrite "*** BEGIN CONVERSION FROM DOC, DOCX, RTF, TXT, HTM, HTML TO PDF ***" 

    Get-ChildItem -Path $documents_path\* -Include *.docx, *.doc, *.rtf, *.txt, *.htm? -recurse | ForEach-Object { 

      $original_document = "$($_.FullName)" 

      # Verifies that a document exists before calling the convert script 
      If ($original_document -ne $null) 
      { 

       Invoke-Expression "$word2PDF $arguments" 

       #checks to see if document was successfully converted and deleted. If not, doc is moved to another directory 
       If(Test-Path -path $original_document) 
       { 
       Move-Item $original_document $failed_path 
       } 
      } 
     } 

    $original_document = $null 

    [gc]::collect() 
    [gc]::WaitForPendingFinalizers() 

這裏是腳本(WordToPDF.ps1),其由主腳本調用:

Param($documents, $pdf_out_path, $Logfile) 

# Function to write to the log file 
Function LogWrite 
{ 
    Param ([string]$logstring) 
    $time = Get-Date -Format "hh:mm:ss:fff" 

    Add-content $Logfile -value "$date $time $logstring" 
} 

$word_app = New-Object -ComObject Word.Application 

$document = $word_app.Documents.Open($_.FullName) 
$original_document = "$($_.FullName)" 

# Creates the output file name with path 
$pdf_document = "$($pdf_out_path)\$($_.BaseName).pdf" 

LogWrite "Converting: $original_document to $pdf_document" 
$document.SaveAs([ref] $pdf_document, [ref] 17) 
$document.Close() 

# Deletes the original document after it has been converted 
Remove-Item $original_document 
LogWrite "Deleting: $original_document" 

$word_app.Quit() 

任何建議,將不勝感激。 謝謝。

回答

1

我只是要評論並將您鏈接到此問題:Can PowerShell run commands in Parallel。然後我注意到這個問題的日期和答案,並且在PowerShell v3.0中,有一些新功能可能對您更好。

問題在於使用PowerShell jobs。哪些可以工作,但需要你跟上工作狀態,所以可以添加一些額外的編碼來管理。

PowerShell v3以workflow打開了一扇門,它基於Windows Workflow Foundation。關於這個新命令如何工作的基礎知識的好文章可以是found on Script Guy's blog here。基本上你可以調整你的代碼運行通過工作流程轉換,它會並行地執行這樣的:

workflow foreachfile { 
    foreach -parallel ($f in $files) { 
    #Put your code here that does the work 
    } 
} 

從什麼我能找到線程限制這已經是在一個時間5個線程。我不確定這是多麼準確,但是blog post here noted the limitation。但是,由於應用程序COM對象的Word和Excel可能非常耗費CPU時間,因此一次執行5個線程可能效果不錯。

+0

對於性能,我會避免PSJobs。如果OP升級到PS v4.0,則在Foreach工作流程中有「-ThrottleLimit」選項。不過,我發現後臺運行空間比工作流更容易理解。 – xXhRQ8sD2L7Z

+0

謝謝,我會試試這個併發布我的結果。 – DaveC

0

我有一個多線程的powershell環境,用於在所有AD設備上進行折衷掃描指示器 - 與Gearman進行了625次的連接。 http://gearman.org

它是開源的,允許跨平臺的選項。它與服務器工作流進行線程連接,並通過Python運行。真正被你們非常推薦的人 - 濫用PowerShell中的線程的人。這不是一個答案,而是我從來沒有聽說過的東西,但是每天都愛和使用。傳遞它。開放源碼的勝利:)

我也使用psjobs之前,他們是偉大的,直到一定的數量級。也許這是我的.net專業知識的缺乏,但ps有一些令人毛骨悚然的細微記憶細微差別,大規模可能會產生一些令人討厭的效果。