COM-объекты при работе в фоновом режиме
Пытаясь создать таблицу в слове и хотел бы немного ускорить процесс, без заданий это работает нормально, но это просто медленно. Когда я запускаю этот скрипт, все работает нормально, кроме случаев, когда скрипт
$Table.Cell($x,<column>).Range.Text = <string>
Выдает ошибку
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (Cell:String) [],
RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
и когда дело доходит до
$table = $doc.tables.item(1)
Выдает ошибку
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (item:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Я предполагаю, что это как-то связано с
[System.Runtime.InteropServices.Marshal]::GetActiveObject('Word.Application')
не принимая всю информацию документа...
Вот мой код
#More code above
$owners = Import-CSV $ownerspath -header @("Owners")
foreach($name in $owners) {
#Document creation
[ref]$SaveFormat = "microsoft.office.interop.word.WdSaveFormat" -as [type]
$Word = New-Object -comobject word.application
$Word.Visible = $false
$Doc = $Word.Documents.Add()
$Range = $Doc.Range()
$owner = $name.Owners
$g = import-csv $exportpath$owner.csv -header @("Server name", "Description", "OS", "OS EOL", "SQL", "SQL EOL")
$path = "$exportpath$owner.docx"
if(($g.count + 1) -eq 1) {
$rows = 2
}
else {
$rows = $g.count + 1
}
#Table creation
$Selection = $word.selection
$Doc.Tables.Add($Range,$Rows,6) | Out-Null
$Table = $Doc.Tables.item(1)
$Table.Style = "Medium Shading 1 - Accent 1"
$Table.Cell(1,1).Range.Text = "Server name"
$Table.Cell(1,2).Range.Text = "Server description"
$Table.Cell(1,3).Range.Text = "OS Version"
$Table.Cell(1,4).Range.Text = "OS EOL Date"
$Table.Cell(1,5).Range.Text = "SQL Version"
$Table.Cell(1,6).Range.Text = "SQL EOL Date"
$x = 2
foreach($l in $g) {
$sn = $l.'Server name'
$d = $l.Description
$oper = $l.OS
$opereol = $l.'OS EOL'
$sequel = $l.SQL
$sequeleol = $l.'SQL EOL'
$scriptblock = {
param($sn, $d, $oper, $opereol, $sequel, $sequeleol, $x)
$word = [System.Runtime.InteropServices.Marshal]::GetActiveObject('Word.Application')
$doc = $word.documents
$table = $doc.tables.item(1)
#Server names, OS, OS EOL, SQL, SQL EOL, and coloring for the EOL dates if the need them are added in this foreach loop.
$Table.Cell($x,1).Range.Text = $sn
$Table.Cell($x,2).Range.Text = $d
$Table.Cell($x,3).Range.Text = $oper
if($l.'OS EOL' -eq 'Out of date') {
$Table.Cell($x,4).Range.shading.BackgroundPatternColor = 255
$Table.Cell($x,4).Range.Text = $opereol
$OoDTotal += 1
}
elseif($l.'OS EOL' -like "*!*") {
$Table.Cell($x,4).Range.shading.BackgroundPatternColor = 65535
$Table.Cell($x,4).Range.Text = $opereol
$CloseTotal += 1
}
else {
$Table.Cell($x,4).Range.Text = $opereol
$UtDTotal += 1
}
$Table.Cell($x,5).Range.Text = $sequel
if($l.'SQL EOL' -eq 'Out of date') {
$Table.Cell($x,6).Range.shading.BackgroundPatternColor = 255
$Table.Cell($x,6).Range.Text = $sequeleol
$OoDTotal += 1
}
elseif($l.'SQL EOL' -like "*!*") {
$Table.Cell($x,6).Range.shading.BackgroundPatternColor = 65535
$Table.Cell($x,6).Range.Text = $sequeleol
$CloseTotal += 1
}
else {
$Table.Cell($x,6).Range.Text = $sequeleol
$UtDTotal += 1
}
}
Start-Job $scriptblock -ArgumentList $sn, $d, $oper, $opereol, $sequel, $sequeleol, $x
$x++
}
while(get-job -state "Running") {
start-sleep -seconds 1
}
Get-Job | Receive-Job
Get-Job | Remove-Job
#More code below
РЕДАКТИРОВАТЬ: я запускаю этот скрипт на Posh V2 с Office Word 2007
1 ответ
Это ограниченная проблема. Вы не передаете все необходимые объекты (например, по крайней мере, и наиболее конкретно, объект Word COM) в свой блок скриптов. Задания PowerShell фактически создают совершенно отдельные экземпляры процесса powershell. Идите и проверьте:
Start-Job -ScriptBlock { start-sleep -Seconds 20 }
Start-Job -ScriptBlock { start-sleep -Seconds 20 }
PS C:\Users\hiyo!> Get-Process powershell
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName
------- ------ ----- ----- ----- ------ -- -- -----------
388 22 40336 48820 ...54 0.45 2720 1 powershell
443 25 54360 66860 ...75 0.58 7240 1 powershell
И если вы на самом деле попытаетесь выполнить это так, как вам нужно, и передать все нужные параметры, вы можете столкнуться с проблемами блокировки записи, пытаясь открыть несколько экземпляров файла для R/W...