A desktop publishing application from Microsoft that focuses on page layout and graphic design.
We ran into issues/error messages caused by long file names and wildcard characters. This is the adjusted script to handle those issues; I converted 25 years worth/ 33,000 files with this script. So far the PDF files are perfect.
<#
.SYNOPSIS
Converts Microsoft Publisher .pub files to PDF format.
.DESCRIPTION
This script automates the conversion of Microsoft Publisher (.pub) files to PDF format using the Microsoft Office Interop Publisher library.
It processes all files matching the specified filter, checks if a PDF already exists for each file, and skips conversion if the PDF is present.
The script logs successful conversions and any errors encountered during the process.
Updated to fully support Windows Long Paths (>260 characters) and wildcard filters.
.PARAMETER Filter
Specifies the file filter to select Publisher files for conversion.
This can be a specific file name (e.g., "document.pub") or a wildcard pattern (e.g., "*.pub").
.PARAMETER Recurse
If specified, searches for Publisher files recursively in all subdirectories that match the filter. If omitted, only the current directory is searched.
#>
param
(
[ValidateNotNullOrEmpty()]
[string]
$Filter,
[switch]
$Recurse
)
if (-not $PSBoundParameters.ContainsKey('Filter')) {
Write-Error "The -Filter parameter is required."
exit 1
}
if (-not ($Filter -like "*.pub")) {
Write-Error "The filter must specify .pub files (e.g., '*.pub' or 'file.pub').";
exit 1;
}
try {
# Safely determine the search directory and file pattern without letting GetFullPath choke on wildcards
$resolvedFilter = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Filter)
if ([System.IO.Directory]::Exists($resolvedFilter)) {
$searchDir = $resolvedFilter
$searchPattern = "*.pub"
} else {
# Split the path into directory and file pattern parts safely
$searchDir = [System.IO.Path]::GetDirectoryName($resolvedFilter)
$searchPattern = [System.IO.Path]::GetFileName($resolvedFilter)
# If the directory part still contains wildcards, strip them to find the base path
if ($searchDir -like "*[*?]*") {
Write-Error "Wildcards are only supported in the filename/extension part of the filter, not in folder names."
exit 1
}
}
if (-not [System.IO.Directory]::Exists($searchDir)) {
Write-Error "The directory does not exist: $searchDir"
exit 1
}
# Use modern dotnet enumeration which natively ignores the 260 character path limit
$searchOption = if ($Recurse) { [System.IO.SearchOption]::AllDirectories } else { [System.IO.SearchOption]::TopDirectoryOnly }
try {
$rawFiles = [System.IO.Directory]::EnumerateFiles($searchDir, $searchPattern, $searchOption)
$files = @()
foreach ($f in $rawFiles) {
$files += New-Object System.IO.FileInfo($f)
}
} catch {
Write-Error "Error finding files: $_"
exit 1
}
if ($files.Count -eq 0) {
Write-Error "No Publisher files found for the filter: $Filter";
exit 1;
}
Write-Output "Running...";
Add-type -AssemblyName Office;
Add-type -AssemblyName Microsoft.Office.Interop.Publisher;
try {
$app = New-Object -ComObject Publisher.Application;
} catch {
Write-Error "Microsoft Publisher is not installed or accessible.";
exit 1;
}
$successCount = 0;
$failCount = 0;
foreach ($file in $files) {
if ($file.Extension -eq ".pub") {
$fileFullName = $file.FullName;
# Prepend long path escape prefix if the path length exceeds standard limits
if ($fileFullName.Length -ge 240 -and -not $fileFullName.StartsWith("\\?\")) {
if ($fileFullName.StartsWith("\\")) {
# Network UNC paths
$fileFullName = "\\?\UNC\" + $fileFullName.Substring(2)
} else {
# Local drive paths
$fileFullName = "\\?\" + $fileFullName
}
}
$pdfFilePath = [System.IO.Path]::ChangeExtension($fileFullName, '.pdf')
# Use dotnet's Exists check to circumvent standard Test-Path path length limitations
if ([System.IO.File]::Exists($pdfFilePath)) {
Write-Error "PDF file already exists: $pdfFilePath";
$failCount++;
Continue;
}
# Open the file
try {
$doc = $app.Open($fileFullName);
} catch {
$failCount++;
Write-Error "Error opening file: $fileFullName $_";
Continue;
}
if (-not($doc)) {
$failCount++;
Write-Error "Failed to open file: $fileFullName";
Continue;
}
try {
# Export file as PDF
$doc.ExportAsFixedFormat([Microsoft.Office.Interop.Publisher.PbFixedFormatType]::pbFixedFormatTypePDF, $pdfFilePath);
if ([System.IO.File]::Exists($pdfFilePath)) {
Write-Output "Exported to $pdfFilePath.";
$successCount++;
} else {
$failCount++;
Write-Error "Failed to export file: $fileFullName";
}
} catch {
$failCount++;
Write-Error "Error during export: $_";
}
$doc.Close();
}
}
#Log output
Write-Output "Converted $successCount files with $failCount errors.";
}catch{
Write-Error $_;
}finally {
if ($app) {
#Quit Publisher
$app.Quit();
}
}