Ошибки команды Powershell Word SaveAs при запуске с использованием учетной записи службы - PullRequest
0 голосов
/ 09 января 2020

Это сводило меня с ума в течение нескольких дней .... У меня есть скрипт powershell, который преобразует все файлы .do c в целевом каталоге в PDF с помощью взаимодействия Word SaveAs.
Этот скрипт работает нормально при запуске в контекст вошедшего в систему пользователя, но с ошибками « Вы не можете вызвать метод для выражения с нулевым значением. », когда я пытаюсь выполнить сценарий, используя учетную запись службы (через задачу планировщик, запускается от имени другого пользователя) ... учетная запись службы имеет права локального администратора.

В этой строке возникает исключение: $ Do c .SaveAs ([ref] $ Name.value, [ ref] 17)

Мой код выглядит следующим образом: я не лучший кодер в мире, поэтому любые советы будут с благодарностью приняты. спасибо.

try
{
$FileSource = 'D:\PROCESSOR\NewArrivals\*.doc'
$SuccessPath = 'D:\PROCESSOR\Success\'
$docextn='.doc'
$Files=Get-ChildItem -path $FileSource
$counter = 0
$filesProcessed = 0
$Word = New-Object -ComObject Word.Application

#check files exist to be processed.
$WordFileCount = Get-ChildItem $FileSource -Filter *$docextn -File| Measure-Object | %{$_.Count} -ErrorAction Stop

If ($WordFileCount -gt 0) {

  Foreach ($File in $Files) {
    $Name="$(($File.FullName).substring(0, $File.FullName.lastIndexOf("."))).pdf"

    $Doc = $Word.Documents.Open($File.FullName)
    $Doc.SaveAs([ref]$Name.value,[ref]17)
    $Doc.Close()

    if ($counter -gt 100) {
        $counter = 0
        $Word.Quit()
        [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word)
        $Word = New-Object -ComObject Word.Application
    }
    $counter = $counter + 1
    $filesProcessed = $filesProcessed + 1
}
}
$Word.Quit()
        [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word)
}

catch
{
}
finally
{
}

1 Ответ

0 голосов
/ 09 января 2020

Если вы уверены, что учетная запись службы имеет доступ к Word, я думаю, что исключение, с которым вы сталкиваетесь, - [ref] при выполнении SaveAs (). AKAIK только для версий Office ниже 2010 года требуется [ref], для версий выше - нет.

Далее, я думаю, что ваш код может быть несколько изменен, например, путем освобождения объектов com ($ Do c и $ Word) внутри блока finally, поскольку это всегда выполняется. Кроме того, нет необходимости выполнять Get-ChildItem дважды.

Примерно так:

$SuccessPath    = 'D:\PROCESSOR\Success'
$FileSource     = 'D:\PROCESSOR\NewArrivals'
$filesProcessed = 0

try {
    $Word = New-Object -ComObject Word.Application
    $Word.Visible = $false
    # get a list of FileInfo objects that have the .doc extension and loop through
    Get-ChildItem -Path $FileSource -Filter '*.doc' -File | ForEach-Object {
        # change the extension to pdf for the output file
        $pdf = [System.IO.Path]::ChangeExtension($_.FullName, '.pdf')
        $Doc = $Word.Documents.Open($_.FullName)

        # Check Version of Office Installed. Pre 2010 versions need the [ref]
        if ($word.Version -gt '14.0') {
            $Doc.SaveAs($pdf, 17)
        }
        else {
            $Doc.SaveAs([ref]$pdf,[ref]17)
        }
        $Doc.Close($false)
        $filesProcessed++
    }
}
finally {
    # cleanup code
    if ($Word) {
        $Word.Quit()
        $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($Doc)
        $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($Word)
        [System.GC]::Collect()
        [System.GC]::WaitForPendingFinalizers()
        $Word = $null
    }
}

Тогда возникает вопрос $SuccessPath. Вы никогда не используете это. Вы хотите сохранить PDF-файлы по этому пути? Если это так, измените строку

$pdf = [System.IO.Path]::ChangeExtension($_.FullName, '.pdf')

на

$pdf = Join-Path -Path $SuccessPath -ChildPath ([System.IO.Path]::ChangeExtension($_.Name, '.pdf'))

Надеюсь, что это поможет

...