【问题标题】:Powershell Word SaveAs command errors when run using a service account使用服务帐户运行时出现 Powershell Word SaveAs 命令错误
【发布时间】:2020-01-08 21:29:57
【问题描述】:

这几天让我发疯......我有一个 powershell 脚本,它使用 Word SaveAs 互操作将目标目录中的所有 .doc 文件转换为 PDF。
该脚本在登录用户的上下文中运行时工作正常,但当我尝试执行时出现“您不能在空值表达式上调用方法。”错误使用服务帐户的脚本(通过任务计划程序,以其他用户身份运行)...服务帐户具有本地管理员权限。

异常发生在这一行:$Doc.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
{
}

【问题讨论】:

    标签: powershell ms-word


    【解决方案1】:

    如果您确定服务帐户可以访问 Word,那么我认为您在执行 SaveAs() 时遇到的异常是在 [ref] 中。 只有 AKAIK 2010 以下的 Office 版本需要[ref],以上版本不需要。

    接下来我认为你的代码可以稍微整理一下,例如通过释放finally 块内的com 对象($Doc 和$Word),因为它总是被执行。 此外,无需执行两次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'))
    

    希望有帮助

    【讨论】:

    • 谢谢@theo。我使用的是 Word 2016,所以删除了 [ref] 但仍然遇到同样的问题。尝试运行您的代码时出现异常: ForEach-Object : Argument: '1' 应该是 System.Management.Automation.PSReference。使用[参考]。在 Get-ChildItem -Path $FileSource -Filter '*.doc' -File | ForEach-Object {
    • @GBense 那么您确定服务帐户可以访问文件夹$FileSource 中的文件吗?
    • 是的,当我的脚本手动执行时,所有工作都按预期工作。此外,我已经检查了文件级别的权限是否正常。
    • @GBense 我无法使用上面的代码重现该错误(或事实上的任何错误)。请确保直接在 PowerShell 编辑器中复制/粘贴(而不是通过 Word 或 Outlook,因为这样引号将变成不属于代码的卷曲印刷物)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2013-10-11
    • 2021-10-08
    • 2023-03-21
    • 2021-01-08
    相关资源
    最近更新 更多