Testen des Word-Automation Service

Neulich kam die Frage auf, ob man den WordAutomationService von SharePoint irgendwie testen könnte.. Oder auch “direkt” starten um dabei das ULS-Log zu beobachten.

Ich habe dazu ein Skript erstellt, mit dem ein Dokument aus dem SharePoint (dieses muss existieren und in einem der unterstützten Formate vorliegen) direkt konvertiert werden kann.

<#
.SYNOPSIS
Tests the WordAutomationService by submitting a document and waiting for the results.
.PARAMETER InFile
Url (in SharePoint) that points to the document to convert
This documents should exist.
.PARAMETER OutFile
Url (in SharePoint) to place the converted document
This documents should *not* exist.
.PARAMETER Format
Format of the output. PDF or XPS. Default: PDF
.EXAMPLE
Test-WordAutomationService -InFile https://my.sp.farm/documents/word-doc.docx -OutFile https://my.sp.farm/documents/converted.pdf
Converts https://my.sp.farm/documents/word-doc.docx to pdf and saves the result to https://my.sp.farm/documents/converted.pdf
#>
[CmdletBinding()]
[OutputType([System.Collections.Specialized.StringCollection])]
param (
[Parameter(Mandatory=$true)]
[string]$InFile,
[Parameter(Mandatory=$true)]
[string]$OutFile,
[Parameter(Mandatory=$false)]
[ValidateSet("pdf", "xps")]
[string]$Format = "pdf"
)
$ErrorActionPreference="Stop"
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
$tmp = [Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Word.Server")
if($tmp -eq $null) {
throw "Could not load Microsoft.Office.Word.Server.dll. Somethong is not right..."
}
Write-Verbose "Assembly $($tmp.GetName().Name) is present and loaded"
$serviceApp = Get-SPServiceApplication | Where-Object { $_.TypeName -eq "Word Automation Services" } | Select-Object -First 1
if($null -eq $serviceApp) {
throw "Could not find Word Automation Services Service Application. Somethong is not right..."
}
Write-Verbose "Using Service-Application $($serviceApp.Name)."
#TODO: Service app as param? what if there's more than one?!
$serviceAppProxy = Get-SPServiceApplicationProxy | Where-Object { $_.ServiceEndpointUri -eq $serviceApp.Uri.AbsoluteUri }
Write-Verbose "Using Service-ApplicationProxy $($serviceAppProxy.Name)."
$web = $null
$url = $InFile
while ($null -eq $web) {
if([string]::isNullOrEmpty($url)){
throw "could not find a viable web from url: $($InFile)"
}
$url = (Split-Path -Path $url -Parent).Replace("\", "/")
$web = Get-SPWeb $url -ErrorAction Ignore
}
Write-Verbose "Using web: $($web) ($($web.Url))"
$setting = New-Object "Microsoft.Office.Word.Server.Conversions.ConversionJobSettings"
$setting.OutputFormat = $Format.ToUpperInvariant()
$job = New-Object "Microsoft.Office.Word.Server.Conversions.ConversionJob" -ArgumentList @($serviceAppProxy.Id, $setting)
$job.UserToken = $web.CurrentUser.UserToken
$job.AddFile($InFile, $OutFile)
$job.Start()
Write-Verbose "Started conversion-job with id: $($job.JobId)"
$timer = Get-SPTimerJob | Where-Object { $_.TypeName -like "Word Automation Services Timer Job" } | Select-Object -First 1
Start-SPTimerJob $timer
Write-Verbose "TimerJob '$($timer.DisplayName)' started."
$status = New-Object "Microsoft.Office.Word.Server.Conversions.ConversionJobStatus" -ArgumentList @($serviceAppProxy.Id, $job.JobId, $null);
while (($status.NotStarted -ge 1) -or ($status.InProgress -ge 1)) {
Write-Verbose "In Progress: $($status.InProgress)"
Start-Sleep -Seconds 1
$status.Refresh()
}
$items = $status.GetItems("Succeeded,Failed,Canceled")
Write-Verbose "Job ended. $($items.Length) items in this job."
,($items) #write them...

Das Skript erstellt einen neuen Job für den WordAutomationService, startet den entsprechenden TimerJob (“Word Automation Services Timer Job“) und wartet bis die Konvertierung abgeschlossen ist. Das Ergebnis ggf. mit Fehlermeldung wird ausgegeben.

Wenn der WordAutomationService nicht läuft wie gewünscht, ist für mich immer die erste Anlaufstelle der Troubleshooting Guideline.

(Alle links beziehen sich auf SharePoint 2010 – es hat sich aber seit dem zu 2016/2019 nichts geändert.)