begin { # check to see whether the PDF printer was set up correctly $printerName = "PrintPDFUnattended" $printer = Get-Printer-Name$printerName-ErrorAction SilentlyContinue if (!$?) { $TempPDF = "$env:temp\tempPDFResult.pdf" $port = Get-PrinterPort-Name$TempPDF-ErrorAction SilentlyContinue if ($port-eq$null) { # create printer port Add-PrinterPort-Name$TempPDF }
# add printer Add-Printer-DriverName"Microsoft Print to PDF"-Name$printerName-PortName$TempPDF } else { # this is the file the print driver always prints to $TempPDF = $printer.PortName
# is the port name is the output file path? if ($TempPDF-notlike'?:\*') { throw"Printer $printerName is not set up correctly. Remove the printer, and try again." } }
# make sure old print results are removed $exists = Test-Path-Path$TempPDF if ($exists) { Remove-Item-Path$TempPDF-Force }
# create an empty arraylist that takes the piped results [Collections.ArrayList]$collector = @() }
process { $null = $collector.Add($InputObject) }
end { # send anything that is piped to this function to PDF $collector | Out-Printer-Name$printerName
# wait for the print job to be completed, then move file $ok = $false do { Start-Sleep-Milliseconds500 Write-Host'.'-NoNewline
$fileExists = Test-Path-Path$TempPDF if ($fileExists) { try { Move-Item-Path$TempPDF-Destination$Path-Force-ea Stop $ok = $true } catch { # file is still in use, cannot move # try again } } } until ( $ok ) Write-Host
# open file if requested if ($Open) { Invoke-Item-Path$Path } } }
假设您使用的是 Windows 10 或 Windows 2016,并且 “Microsoft Print to PDF” 打印机可用,那么您可以像这样方便地创建 PDF 文档:
在前一个技能中我们解释了如何在 Windows 10 和 Windows Server 2016 中使用 PowerShell 来设置一个能将任何东西打印到 PDF 文件的打印机,当然,是无人值守的。要使它真的发挥作用,我们将它封装为一个名为 Out-PDFFile 的函数。任何通过管道传给这个新命令的内容都会被转换为一个 PDF 文件。
# check to see whether the PDF printer was set up correctly $printerName = "PrintPDFUnattended" $printer = Get-Printer-Name$printerName-ErrorAction SilentlyContinue if (!$?) { Write-Warning"Printer $printerName does not exist." Write-Warning"Make sure you have created this printer (see previous tips)!" return }
# this is the file the print driver always prints to $TempPDF = $printer.PortName
# is the printer set up correctly and the port name is the output file path? if ($TempPDF-notlike'?:\*') { Write-Warning"Printer $printerName is not set up correctly." Write-Warning"Make sure you have created this printer as instructed (see previous tips)!" return }
# make sure old print results are removed $exists = Test-Path-Path$TempPDF if ($exists) { Remove-Item-Path$TempPDF-Force }
# send anything that is piped to this function to PDF $input | Out-Printer-Name$printerName
# wait for the print job to be completed, then move file $ok = $false do { Start-Sleep-Milliseconds500 Write-Host'.'-NoNewline
$fileExists = Test-Path-Path$TempPDF if ($fileExists) { try { Move-Item-Path$TempPDF-Destination$Path-Force-ea Stop $ok = $true } catch { # file is still in use, cannot move # try again } } } until ( $ok ) Write-Host
# open file if requested if ($Open) { Invoke-Item-Path$Path } }
psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There aren’t too many trainings around for experienced PowerShell scripters where you really still learn something new. But there’s one place you don’t want to miss: PowerShell Conference EU - with 40 renown international speakers including PowerShell team members and MVPs, plus 350 professional and creative PowerShell scripters. Registration is open at www.psconf.eu, and the full 3-track 4-days agenda becomes available soon. Once a year it’s just a smart move to come together, update know-how, learn about security and mitigations, and bring home fresh ideas and authoritative guidance. We’d sure love to see and hear from you!
# requires Windows 10 / Windows Server 2016 or better
# choose a name for your new printer $printerName = 'PrintPDFUnattended' # choose a default path where the PDF is saved $PDFFilePath = "$env:temp\PDFResultFile.pdf" # choose whether you want to print a test page $TestPage = $true
# see whether the driver exists $ok = @(Get-PrinterDriver-Name"Microsoft Print to PDF"-ea0).Count -gt0 if (!$ok) { Write-Warning"Printer driver 'Microsoft Print to PDF' not available." Write-Warning"This driver ships with Windows 10 or Windows Server 2016." Write-Warning"If it is still not available, enable the 'Printing-PrintToPDFServices-Features'" Write-Warning"Example: Enable-WindowsOptionalFeature -Online -FeatureName Printing-PrintToPDFServices-Features" return }
# check whether port exists $port = Get-PrinterPort-Name$PDFFilePath-ErrorAction SilentlyContinue if ($port-eq$null) { # create printer port Add-PrinterPort-Name$PDFFilePath }
# add printer Add-Printer-DriverName"Microsoft Print to PDF"-Name$printerName-PortName$PDFFilePath
# print a test page to the printer if ($TestPage) { $printerObject = Get-CimInstance Win32_Printer -Filter"name LIKE '$printerName'" $null = $printerObject | Invoke-CimMethod-MethodName printtestpage Start-Sleep-Seconds1 Invoke-Item-Path$PDFFilePath }
Windows 10 和 Windows Server 2016 终于带来了内置的 PDF 打印机,名为 “Microsoft Print to PDF”。您可以在 PowerShell 中用它来创建 PDF 文件。请运行这段代码来测试您的 PDF 打印机:
1 2 3 4 5 6 7 8 9
$printer = Get-Printer-Name"Microsoft Print to PDF"-ErrorAction SilentlyContinue if (!$?) { Write-Warning"Your PDF Printer is not yet available!" } else { Write-Warning"PDF printer is ready for use." }
如果您的打印机不能用(或是暂时不能用),那么您可能使用的不是 Windows 10 或 Windows Server 2016,或者 PDF 打印功能尚未启用。请在管理员权限下运行 PowerShell 并执行这段命令来修复它:
# make sure the watcher emits events $FileSystemWatcher.EnableRaisingEvents = $true
# define the code that should execute when a file change is detected $Action = { $details = $event.SourceEventArgs $Name = $details.Name $FullPath = $details.FullPath $OldFullPath = $details.OldFullPath $OldName = $details.OldName $ChangeType = $details.ChangeType $Timestamp = $event.TimeGenerated $text = "{0} was {1} at {2}"-f$FullPath, $ChangeType, $Timestamp Write-Host"" Write-Host$text-ForegroundColor Green
# you can also execute code based on change type here switch ($ChangeType) { 'Changed' { "CHANGE" } 'Created' { "CREATED"} 'Deleted' { "DELETED" # uncomment the below to mimick a time intensive handler <# Write-Host "Deletion Handler Start" -ForegroundColor Gray Start-Sleep -Seconds 4 Write-Host "Deletion Handler End" -ForegroundColor Gray #> } 'Renamed' { # this executes only when a file was renamed $text = "File {0} was renamed to {1}"-f$OldName, $Name Write-Host$text-ForegroundColor Yellow } default { Write-Host$_-ForegroundColor Red -BackgroundColor White } } }
Write-Host"Monitoring content of $PathToMonitor" explorer $PathToMonitor while ($true) { $Change = $FileSystemWatcher.WaitForChanged('All', 1000) if ($Change.TimedOut -eq$false) { # get information about the changes detected Write-Host"Change detected:" $Change | Out-Default
# uncomment this to see the issue #Start-Sleep -Seconds 5 } else { Write-Host"."-NoNewline } }
这个示例可以正常工作。当您向监控的文件夹增加文件,或者作出改变时,将会监测到改变的类型。您可以容易地得到该信息并采取操作。例如,对于 IT 部门,人们可以向一个投放文件夹投放文件和说明,您的脚本可以自动处理这些文件。
# set the event log name you want to subscribe to # (use Get-EventLog -AsString for a list of available event log names) $Name = 'Application'
# get an instance $Log = [System.Diagnostics.EventLog]$Name
# determine what to do when an event occurs $Action = { # get the original event entry that triggered the event $entry = $event.SourceEventArgs.Entry
# log all events Write-Host"Received from $($entry.Source): $($entry.Message)"
# do something based on a specific event if ($entry.EventId -eq1-and$entry.Source -eq'WinLogon') { Write-Host"Test event was received!"-ForegroundColor Red }
}
# subscribe to its "EntryWritten" event $job = Register-ObjectEvent-InputObject$log-EventName EntryWritten -SourceIdentifier'NewEventHandler'-Action$Action
# now whenever an event is written to the log, $Action is executed # use a loop to keep PowerShell busy. You can abort via CTRL+C
Write-Host"Listening to events"-NoNewline
try { do { Wait-Event-SourceIdentifier NewEventHandler -Timeout1 Write-Host"."-NoNewline
} while ($true) } finally { # this executes when CTRL+C is pressed Unregister-Event-SourceIdentifier NewEventHandler Remove-Job-Name NewEventHandler Write-Host"" Write-Host"Event handler stopped." }
Simply “convert” the event log name into an object of “EventLog” type. The result looks similar to this and provides information about the number of entries and the log file size: 只需要将时间日志名称“转换”为一个 “EventLog“ 类型的对象。结果类似这样,并且提供了条目的数量和日志文件尺寸等信息:
1 2 3 4 5
PS> $systemLogDirect
Max(K) Retain OverflowAction Entries Log ------------------------------------ 20.4800 OverwriteAsNeeded 19.806 System