PowerShell 技能连载 - 将 PowerShell 结果发送到 PDF(第 4 部分)

在前一个技能中我们将建了 Out-PDFFile 函数,能够接受任意 PowerShell 的结果数据并将它们转换为 PDF 文件——使用 Windows 10 和 Windows Server 2016 内置的打印驱动。

我们使用了一个简单的函数,用 $Input 自动变量来读取管道输入的数据,从而达到上述目的。如果您更希望使用高级函数,利用它们的必选参数等功能,我们将该工程包装成一个更优雅的高级函数,它能够在检测到未安装 PDF 打印机的情况下先安装它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
function Out-PDFFile
{
param
(
[Parameter(Mandatory)]
[String]
$Path,

[Parameter(ValueFromPipeline)]
[Object]
$InputObject,

[Switch]
$Open
)

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 -Milliseconds 500
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 文档:

1
2
3
PS> Get-Service | Out-PDFFile -Path $home\desktop\services.pdf -Open

PS> Get-ComputerInfo | Out-PDFFile -Path $home\Desktop\computerinfo.pdf -Open

如果指定的 “PrintPDFUnattended” 打印机还未安装,该函数也会事先安装该打印机。

PowerShell 技能连载 - 将 PowerShell 结果发送到 PDF(第 3 部分)

在前一个技能中我们解释了如何在 Windows 10 和 Windows Server 2016 中使用 PowerShell 来设置一个能将任何东西打印到 PDF 文件的打印机,当然,是无人值守的。要使它真的发挥作用,我们将它封装为一个名为 Out-PDFFile 的函数。任何通过管道传给这个新命令的内容都会被转换为一个 PDF 文件。

注意:要让这个函数生效,您必须按前一个技能介绍的方法先创建一个名为 PrintPDFUnattended 的打印机!

以下是 Out-PDFFile 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
function Out-PDFFile
{
param
(
$Path = "$env:temp\results.pdf",

[Switch]
$Open
)

# 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 -Milliseconds 500
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
}
}

现在导出结果到 PDF 文件十分简单:

1
2
3
PS> Get-Service | Out-PDFFile -Path $home\desktop\services.pdf -Open

PS> Get-ComputerInfo | Out-PDFFile -Path $home\Desktop\computerinfo.pdf -Open

哇哦,真简单!

请注意我们有意地创建了一个“简单函数”。通过这种方式,所有通过管道输入的数据都可以在 $Input 自动变量中见到。如果您向参数添加属性,例如要使参数成为必选的,这个函数就变成了“高级函数”,并且 $Input 就不存在了。我们将在明天解决这个问题。


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!

PowerShell 技能连载 - 将 PowerShell 结果发送到 PDF(第 2 部分)

在前一个示例中我们延时了如何使用内置的 “Microsoft Print to PDF” 打印机来将 PowerShell 输出结果发送到 PDF 文件。然而,这个打印机会提示选择选择输出的文件,所以不适合自动化任务。

要禁止文件提示,有一个很少人知道的秘密:只需要对打印机指定一个端口,端口名就是输出的文件路径。换句话说,运行这段代码可以创建一个新打印机,并打印到您选择的文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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" -ea 0).Count -gt 0
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 -Seconds 1
Invoke-Item -Path $PDFFilePath
}

当这段脚本执行以后,可以获得一个全新的名为 PrintPDFUnattended 的打印机。并且当打印到该打印机不会产生提示,而是永远输出到临时文件夹的 PDFResultFile.pdf

以下是一段演示如何从 PowerShell 打印 PDF 文件而不产生对话框的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# specify the path to the file you want to create
# (adjust if you want)
$OutPath = "$home\desktop\result.pdf"

# this is the file the print driver always prints to
$TempPDF = "$env:temp\PDFResultFile.pdf"

# make sure old print results are removed
$exists = Test-Path -Path $TempPDF
if ($exists) { Remove-Item -Path $TempPDF -Force }

# send PowerShell results to PDF
Get-Service | Out-Printer -Name "PrintPDFUnattended"

# wait for the print job to be completed, then move file
$ok = $false
do {
Start-Sleep -Milliseconds 500
Write-Host '.' -NoNewline

$fileExists = Test-Path -Path $TempPDF
if ($fileExists)
{
try
{
Move-Item -Path $TempPDF -Destination $OutPath -Force -ErrorAction Stop
$ok = $true
}
catch
{
# file is still in use, cannot move
# try again
}
}
} until ( $ok )
Write-Host

# show new PDF file in explorer
explorer "/select,$OutPath"

当运行这段代码时,将会在桌面上创建一个新的 result.pdf 文件。它包含了所有服务的列表。您可以将任何结果通过管道输出到 Out-Printer 来创建 PDF 文件。

PowerShell 技能连载 - 将 PowerShell 结果发送到 PDF(第 1 部分)

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 并执行这段命令来修复它:

1
PS> Enable-WindowsOptionalFeature -Online -FeatureName Printing-PrintToPDFServices-Features

请确保使用管理员权限运行上述代码,您也可以试着使用以下代码:

1
2
3
$code = 'Enable-WindowsOptionalFeature -Online -FeatureName Printing-PrintToPDFServices-Features'

Start-Process -Verb Runas -FilePath powershell.exe -ArgumentList "-noprofile -command $code"

当 PDF 打印机安装好后,从 PowerShell 中创建 PDF 文件十分简单。只需要将输出结果发送到 Out-Printer。以下是一个示例:

1
PS> Get-Service | Out-Printer -Name "Microsoft Print to PDF"

打印机驱动将会打开一个对话框,您可以选择输出的文件名。如果不希望显示这个对话框,而以无人值守的方式打印,我们将在明天介绍。

PowerShell 技能连载 - 在打印机上打印测试页

感谢 PrintManagement 模块为 Windows 10 和 Windows Server 2016 提供了大量的打印功能支持。如果希望打印官方的测试页,您还需要动用 WMI。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#requires -Version 3.0 -Modules CimCmdlets, PrintManagement

Get-Printer |
Out-GridView -Title 'Print test page on selected printers' -OutputMode Multiple |
ForEach-Object {
$printerName = $_.Name
$result = Get-CimInstance Win32_Printer -Filter "name LIKE '$printerName'" |
Invoke-CimMethod -MethodName printtestpage
if ($result.ReturnValue -eq 0)
{
"Test page printed on $printerName."
}
else
{
"Unable to print test page on $printerName."
"Error code $($result.ReturnValue)."
}
}

当这段代码运行时,将弹出一个对话框显示所有的打印机。请选择一个(或按住 CTRL 选择多个),将在选中的打印机上打印测试页。

PowerShell 技能连载 - 正确使用 FileSystemWatcher(第 2 部分)

在前一个技能中我们介绍了 FileSystemWatcher 并演示了当事件处理代码执行事件过长时会丢失文件系统改变事件。

要正确地使用 FileSystemWatcher,您需要异步地使用它并使用队列。这样即便脚本正忙于处理文件系统变更,也能够继续记录新的文件系统变更,并在一旦 PowerShell 处理完之前的变更时处理新的变更。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# make sure you adjust this to point to the folder you want to monitor
$PathToMonitor = "c:\test"

explorer $PathToMonitor

$FileSystemWatcher = New-Object System.IO.FileSystemWatcher
$FileSystemWatcher.Path = $PathToMonitor
$FileSystemWatcher.IncludeSubdirectories = $true

# 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 }
}
}

# add event handlers
$handlers = . {
Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Changed -Action $Action -SourceIdentifier FSChange
Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Created -Action $Action -SourceIdentifier FSCreate
Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Deleted -Action $Action -SourceIdentifier FSDelete
Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Renamed -Action $Action -SourceIdentifier FSRename
}

Write-Host "Watching for changes to $PathToMonitor"

try
{
do
{
Wait-Event -Timeout 1
Write-Host "." -NoNewline

} while ($true)
}
finally
{
# this gets executed when user presses CTRL+C
# remove the event handlers
Unregister-Event -SourceIdentifier FSChange
Unregister-Event -SourceIdentifier FSCreate
Unregister-Event -SourceIdentifier FSDelete
Unregister-Event -SourceIdentifier FSRename
# remove background jobs
$handlers | Remove-Job
# remove filesystemwatcher
$FileSystemWatcher.EnableRaisingEvents = $false
$FileSystemWatcher.Dispose()
"Event Handler disabled."
}

当您运行这段代码时,将监控 $PathToMonitor 中定义的文件夹的改变,并且当变更发生时,会触发一条消息。当您按下 CTRL+C 时,脚本停止执行,并且所有事件处理器将在 finally 代码块中清理。

更重要的是:这段代码内部使用队列,所以当短时间内有大量修改发生时,它们将会等到 PowerShell 不忙碌的时候立即执行。您可以取消代码中的注释来演唱处理时间。现在,当一个文件删除后,处理器需要 4 秒钟的额外处理时间。

即便删除了大量文件,它们最终仍将显示出来。这里展示的方式比起前一个技能中基于 WaitForChanged() 的同步处理器更可靠。

PowerShell 技能连载 - 正确使用 FileSystemWatcher(第 1 部分)

FileSystemWatcher 可以监控一个文件或文件夹的改变。当有新文件复制到文件夹,或有文件删除或改变,您的 PowerShell 代码会立刻收到通知。

时常会见到这样的同步监控示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# make sure you adjust this
$PathToMonitor = "c:\test"


$FileSystemWatcher = New-Object System.IO.FileSystemWatcher
$FileSystemWatcher.Path = $PathToMonitor
$FileSystemWatcher.IncludeSubdirectories = $true

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 部门,人们可以向一个投放文件夹投放文件和说明,您的脚本可以自动处理这些文件。

然而,这种方式又一个副作用:当监测到一个变更时,控制权返回到您的脚本,这样它可以处理这些变更。如果这时候另一个文件发生改变,而您的脚本并不是正在等待事件,那么将错过这个事件。您可以很容易地自我检查:

向变更发生时的执行代码中添加一些耗时的语句,例如 “Start-Sleep -Seconds 5“,然后对文件夹做多个改变。如您所见,检测到了第一个变更,但是 PowerShell 会持续五分钟忙碌,而其它改变事件都丢失了。

就在明天的技能中我们将确保您的 FileSystemWatcher 不会跳过任何变更!

PowerShell 技能连载 - 响应新的事件日志条目(第 2 部分)

以下是另一个文件系统任务,听起来复杂,实际并没有那么复杂。假设您需要移除一个文件夹结构中指定层次之下的所有文件夹。以下是实现方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 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 -eq 1 -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 -Timeout 1
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."
}

由于事件处理器是活跃的,PowerShell 每秒输出一个“点”,表示它仍在监听。现在打开另一个 PowerShell 窗口,并且运行以下代码:

1
Write-EventLog -LogName Application -Source WinLogon -EntryType Information -Message test -EventId 1

当写入一个新的应用程序事件日志条目时,事件处理器显示事件的详情。如果事件的 EventID 等于 1 并且事件源为 “WinLogon“,例如我们的测试事件条目,那么将会输出一条红色的信息。

要停止事件监听器,请按 CTRL+C。代码将自动清理并从内存中移除事件监听器。

这都是通过 Wait-Event 实现的:这个 cmdlet 可以等待特定的事件发生。并且当它等待时,PowerShell 可以继续执行事件处理器。当您指定一个超时(以秒为单位),该 cmdlet 将控制权返回给脚本。在我们的栗子中,控制权每秒钟都会返回,使脚本有机会以点的方式输出进度指示器。

如果用户按下 CTRL+C,该脚本并不会立即停止。相反,它会先执行 finally 语句块并确保该事件处理器已清除和移除。

PowerShell 技能连载 - 响应新的事件日志条目(第 1 部分)

如果您希望实时处理新的事件日志条目,以下是当新的事件条目写入时,PowerShell 代码能自动收到通知的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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

# do something based on the event
if ($entry.EventId -eq 1 -and $entry.Source -eq 'WinLogon')
{
Write-Host "Test event was received!"
}

}

# subscribe to its "EntryWritten" event
$job = Register-ObjectEvent -InputObject $log -EventName EntryWritten -SourceIdentifier 'NewEventHandler' -Action $Action

这段代码片段安装了一个后台的事件监听器,每当事件日志产生一个 “EntryWritten” 事件时会触发。当发生该事件时,$Action 中的代码就会执行。它通过查询 $event 变量获取触发该操作的事件。在我们的示例中,当 EventId 等于 1,并且事件源是 “WinLogon“ 时,会写入一条信息。当然,您可以发送一封邮件,写入一条日志,或做任何其它有用的事情。

要查看事件处理器的效果,只需要写一个符合所有要素的测试事件:

1
2
# write a fake test event to trigger
Write-EventLog -LogName Application -Source WinLogon -EntryType Information -Message test -EventId 1

当您运行这段代码时,事件处理器将自动执行并向控制台输出自己的信息。

请注意这个例子将安装一个异步的处理器,并且当 PowerShell 不忙碌的时候会在后台执行,并且在 PowerShell 运行期间都有效。您不能通过 Start-Sleep 或一个循环来保持 PowerShell 忙碌(因为 PowerShell 会忙碌而无法在后台处理事件处理器)。要保持这个事件处理器可响应,您可以通过 -noexit 参数启动脚本:

1
Powershell.exe -noprofile -noexit -file “c:\yourpath.ps1”

要移除事件处理器,请运行以下代码:

1
2
PS> Unregister-Event -SourceIdentifier NewEventHandler
PS> Remove-Job -Name NewEventHandler

PowerShell 技能连载 - 直接存取事件日志

通过 Get-EventLog 命令,您可以轻松地转储任意给定的事件日志内容,然而,如果您希望直接存取某个指定的事件日志,您只能使用 -List 参数来完全转储它们,然后选择其中一个您所关注的:

1
2
$SystemLog = Get-EventLog -List | Where-Object { $_.Log -eq 'System' }
$SystemLog

一个更简单的方式是使用强制类型转换,类似这样:

1
2
$systemLogDirect = [System.Diagnostics.EventLog]'System'
$systemLogDirect

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.480 0 OverwriteAsNeeded 19.806 System