在后台工作时工作的COM对象

时间:2017-06-23 16:36:35

标签: powershell comobject

尝试在单词中创建一个表,并希望加快这个过程,没有工作,这可以正常工作,但它只是很慢。当我运行此脚本时,一切正常,除非脚本到达

$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

编辑:我在带有Office Word 2007的Posh V2上运行此脚本

1 个答案:

答案 0 :(得分:0)

这是一个范围问题。您没有将所有必需的对象(例如,至少也是最具体的Word Word对象)传递到您的scriptblock中。 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打开文件的多个实例......