使用Powershell将一个文件夹的文本文件打印成PDF(保留原来的Base名称)
Using Powershell to Print a Folder of Text files to PDF (Retaining the Original Base name)
第一次发帖 - 但我认为这是一个很好的帖子,因为我花了 2 天的时间进行研究,与当地专家交谈,但仍然没有找到这样做的结果。
必须在大量文件(.txt 文件)上定期启动单个打印作业,并且必须通过打印作业将其转换为本地文件(即通过 PDF 打印机),这保留每个文件的原始基本名称。此外,脚本必须具有高度可移植性。
如果文件只是简单地转换(而不是打印),原始基本文件名未保留,或者打印过程需要在每次打印时手动交互,则将不满足objective。
经过我的研究,PowerShell 目前的情况如下:
问题: 这个脚本除了实际打印文件内容外什么都做。
它遍历文件,"prints" a .pdf,同时保留原始文件名基础;但是 .pdf 是空的。
我知道我遗漏了一些重要的东西(即可能是流使用?);但是找了又找都没能找到。非常感谢任何帮助。
如代码中所述,打印函数的核心是gathered from this post:
# The heart of this script (ConvertTo-PDF) is largley taken and slightly modified from https://social.technet.microsoft.com/Forums/ie/en-US/04ddfe8c-a07f-4d9b-afd6-04b147f59e28/automating-printing-to-pdf?forum=winserverpowershell
# The $OutputFolder variable can be disregarded at the moment. It is an added bonus, and a work in progress, but not cirital to the objective.
function ConvertTo-PDF {
param(
$TextDocumentPath, $OutputFolder
)
Write-Host "TextDocumentPath = $TextDocumentPath"
Write-Host "OutputFolder = $OutputFolder"
Add-Type -AssemblyName System.Drawing
$doc = New-Object System.Drawing.Printing.PrintDocument
$doc.DocumentName = $TextDocumentPath
$doc.PrinterSettings = new-Object System.Drawing.Printing.PrinterSettings
$doc.PrinterSettings.PrinterName = 'Microsoft Print to PDF'
$doc.PrinterSettings.PrintToFile = $true
$file=[io.fileinfo]$TextDocumentPath
Write-Host "file = $file"
$pdf= [io.path]::Combine($file.DirectoryName, $file.BaseName) + '.pdf'
Write-Host "pdf = $pdf"
$doc.PrinterSettings.PrintFileName = $pdf
$doc.Print()
Write-Host "Attempted Print: $pdf"
$doc.Dispose()
}
# get the relative path of the TestFiles and OutpufFolder folders.
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
Write-Host "scriptPath = $scriptPath"
$TestFileFolder = "$scriptPath\TestFiles\"
Write-Host "TestFileFolder = $TestFileFolder"
$OutputFolder = "$scriptPath\OutputFolder\"
Write-Host "OutputFolder = $OutputFolder"
# initialize the files variable with content of the TestFiles folder (relative to the script location).
$files = Get-ChildItem -Path $TestFileFolder
# Send each test file to the print job
foreach ($testFile in $files)
{
$testFile = "$TestFileFolder$testFile"
Write-Host "Attempting Print from: $testFile"
Write-Host "Attemtping Print to : $OutputFolder"
ConvertTo-PDF $testFile $OutputFolder
}
您缺少读取文本文件并将文本传递给打印机的处理程序。它被定义为这样的脚本块:
$PrintPageHandler =
{
param([object]$sender, [System.Drawing.Printing.PrintPageEventArgs]$ev)
# More code here - see below for details
}
并像这样添加到 PrintDocument
对象:
$doc.add_PrintPage($PrintPageHandler)
您需要的完整代码如下:
$PrintPageHandler =
{
param([object]$sender, [System.Drawing.Printing.PrintPageEventArgs]$ev)
$linesPerPage = 0
$yPos = 0
$count = 0
$leftMargin = $ev.MarginBounds.Left
$topMargin = $ev.MarginBounds.Top
$line = $null
$printFont = New-Object System.Drawing.Font "Arial", 10
# Calculate the number of lines per page.
$linesPerPage = $ev.MarginBounds.Height / $printFont.GetHeight($ev.Graphics)
# Print each line of the file.
while ($count -lt $linesPerPage -and (($line = $streamToPrint.ReadLine()) -ne $null))
{
$yPos = $topMargin + ($count * $printFont.GetHeight($ev.Graphics))
$ev.Graphics.DrawString($line, $printFont, [System.Drawing.Brushes]::Black, $leftMargin, $yPos, (New-Object System.Drawing.StringFormat))
$count++
}
# If more lines exist, print another page.
if ($line -ne $null)
{
$ev.HasMorePages = $true
}
else
{
$ev.HasMorePages = $false
}
}
function Out-Pdf
{
param($InputDocument, $OutputFolder)
Add-Type -AssemblyName System.Drawing
$doc = New-Object System.Drawing.Printing.PrintDocument
$doc.DocumentName = $InputDocument.FullName
$doc.PrinterSettings = New-Object System.Drawing.Printing.PrinterSettings
$doc.PrinterSettings.PrinterName = 'Microsoft Print to PDF'
$doc.PrinterSettings.PrintToFile = $true
$streamToPrint = New-Object System.IO.StreamReader $InputDocument.FullName
$doc.add_PrintPage($PrintPageHandler)
$doc.PrinterSettings.PrintFileName = "$($InputDocument.DirectoryName)$($InputDocument.BaseName).pdf"
$doc.Print()
$streamToPrint.Close()
}
Get-Childitem -Path "$PSScriptRoot\TextFiles" -File -Filter "*.txt" |
ForEach-Object { Out-Pdf $_ $_.Directory }
顺便说一下,这是基于此处的官方 Microsoft C# 示例:
第一次发帖 - 但我认为这是一个很好的帖子,因为我花了 2 天的时间进行研究,与当地专家交谈,但仍然没有找到这样做的结果。
必须在大量文件(.txt 文件)上定期启动单个打印作业,并且必须通过打印作业将其转换为本地文件(即通过 PDF 打印机),这保留每个文件的原始基本名称。此外,脚本必须具有高度可移植性。
如果文件只是简单地转换(而不是打印),原始基本文件名未保留,或者打印过程需要在每次打印时手动交互,则将不满足objective。
经过我的研究,PowerShell 目前的情况如下:
问题: 这个脚本除了实际打印文件内容外什么都做。 它遍历文件,"prints" a .pdf,同时保留原始文件名基础;但是 .pdf 是空的。
我知道我遗漏了一些重要的东西(即可能是流使用?);但是找了又找都没能找到。非常感谢任何帮助。
如代码中所述,打印函数的核心是gathered from this post:
# The heart of this script (ConvertTo-PDF) is largley taken and slightly modified from https://social.technet.microsoft.com/Forums/ie/en-US/04ddfe8c-a07f-4d9b-afd6-04b147f59e28/automating-printing-to-pdf?forum=winserverpowershell
# The $OutputFolder variable can be disregarded at the moment. It is an added bonus, and a work in progress, but not cirital to the objective.
function ConvertTo-PDF {
param(
$TextDocumentPath, $OutputFolder
)
Write-Host "TextDocumentPath = $TextDocumentPath"
Write-Host "OutputFolder = $OutputFolder"
Add-Type -AssemblyName System.Drawing
$doc = New-Object System.Drawing.Printing.PrintDocument
$doc.DocumentName = $TextDocumentPath
$doc.PrinterSettings = new-Object System.Drawing.Printing.PrinterSettings
$doc.PrinterSettings.PrinterName = 'Microsoft Print to PDF'
$doc.PrinterSettings.PrintToFile = $true
$file=[io.fileinfo]$TextDocumentPath
Write-Host "file = $file"
$pdf= [io.path]::Combine($file.DirectoryName, $file.BaseName) + '.pdf'
Write-Host "pdf = $pdf"
$doc.PrinterSettings.PrintFileName = $pdf
$doc.Print()
Write-Host "Attempted Print: $pdf"
$doc.Dispose()
}
# get the relative path of the TestFiles and OutpufFolder folders.
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
Write-Host "scriptPath = $scriptPath"
$TestFileFolder = "$scriptPath\TestFiles\"
Write-Host "TestFileFolder = $TestFileFolder"
$OutputFolder = "$scriptPath\OutputFolder\"
Write-Host "OutputFolder = $OutputFolder"
# initialize the files variable with content of the TestFiles folder (relative to the script location).
$files = Get-ChildItem -Path $TestFileFolder
# Send each test file to the print job
foreach ($testFile in $files)
{
$testFile = "$TestFileFolder$testFile"
Write-Host "Attempting Print from: $testFile"
Write-Host "Attemtping Print to : $OutputFolder"
ConvertTo-PDF $testFile $OutputFolder
}
您缺少读取文本文件并将文本传递给打印机的处理程序。它被定义为这样的脚本块:
$PrintPageHandler =
{
param([object]$sender, [System.Drawing.Printing.PrintPageEventArgs]$ev)
# More code here - see below for details
}
并像这样添加到 PrintDocument
对象:
$doc.add_PrintPage($PrintPageHandler)
您需要的完整代码如下:
$PrintPageHandler =
{
param([object]$sender, [System.Drawing.Printing.PrintPageEventArgs]$ev)
$linesPerPage = 0
$yPos = 0
$count = 0
$leftMargin = $ev.MarginBounds.Left
$topMargin = $ev.MarginBounds.Top
$line = $null
$printFont = New-Object System.Drawing.Font "Arial", 10
# Calculate the number of lines per page.
$linesPerPage = $ev.MarginBounds.Height / $printFont.GetHeight($ev.Graphics)
# Print each line of the file.
while ($count -lt $linesPerPage -and (($line = $streamToPrint.ReadLine()) -ne $null))
{
$yPos = $topMargin + ($count * $printFont.GetHeight($ev.Graphics))
$ev.Graphics.DrawString($line, $printFont, [System.Drawing.Brushes]::Black, $leftMargin, $yPos, (New-Object System.Drawing.StringFormat))
$count++
}
# If more lines exist, print another page.
if ($line -ne $null)
{
$ev.HasMorePages = $true
}
else
{
$ev.HasMorePages = $false
}
}
function Out-Pdf
{
param($InputDocument, $OutputFolder)
Add-Type -AssemblyName System.Drawing
$doc = New-Object System.Drawing.Printing.PrintDocument
$doc.DocumentName = $InputDocument.FullName
$doc.PrinterSettings = New-Object System.Drawing.Printing.PrinterSettings
$doc.PrinterSettings.PrinterName = 'Microsoft Print to PDF'
$doc.PrinterSettings.PrintToFile = $true
$streamToPrint = New-Object System.IO.StreamReader $InputDocument.FullName
$doc.add_PrintPage($PrintPageHandler)
$doc.PrinterSettings.PrintFileName = "$($InputDocument.DirectoryName)$($InputDocument.BaseName).pdf"
$doc.Print()
$streamToPrint.Close()
}
Get-Childitem -Path "$PSScriptRoot\TextFiles" -File -Filter "*.txt" |
ForEach-Object { Out-Pdf $_ $_.Directory }
顺便说一下,这是基于此处的官方 Microsoft C# 示例: