事件日志是操作系统用来保存本身及其他程序信息的工具,本文将会介绍如何通过PowerShell脚本阅读事件日志并创建新的日志条目。Windows系统中包含多种事件日志,在Windows XP系统中包括4种主要的事件日志。即应用程序、系统、安全性及Internet Explorer日志,如图1所示。这样用户可以方便地从系统中提取和查看日志,从而了解系统的当前运行情况。本文将会介绍如何通过PowerShell写入和搜索Windows事件日志的方法。
1 写入事件日志
PowerShell写入事件日志的功能很有用,Windows Vista和Windows Server 2008的事件日志均提供了多种管理系统中发生事件的功能。通过使用.NET Framework的System.Diagnostics.EventLog类,即可将信息写入到传统事件日志(即系统、应用程序,以及安全)中;另外还可以创建自己的事件日志,并将日志写入其中。
(1)创建来源
在写入事件日志之前,必须创建来源,来源可以被事件日志用于区别发生该事件的源头。这样如果需要写入共享来源的事件日志中,即可通过属性查询。在创建来源后,还需要为日志对象创建新的实例。将来源与事件日志关联,然后指定要写入的信息。
创建一个名为“WriteToAppLog.ps1”的脚本来实现这个功能,代码如下,后面将根据代码给出相关的说明:
if(![system.diagnostics.eventlog]::sourceExists("ps_script"))
{
$applog = [system.diagnostics.eventlog]::CreateEventSource("ps_script","Application")
}
$applog = New-Object system.diagnostics.eventlog("application",".")
$applog.source = "ps_script"
$applog.writeEntry("test for script write applog")
在该脚本中调用来源需要首先确定是否已经定义此来源并关联了事件日志,为此需要执行非运算。在来源没有定义的情况下进行容错处理,即在来源不存在的情况下创建一个指定来源名的来源。由于在脚本中用system.diagnostics.eventlog类的SourceExist静态方法判断来源是否存在,所以静态方法名前需要加两个冒号。如果来源不存在,则需要创建。在使用CreateEventSource方法时,必须指定来源及要关联到该来源的事件日志的名称。
在定义事件来源后,可以使用New-Object cmdlet创建事件日志的实例。在上面的脚本中,使用变量$applog保存由New-Object cmdlet返回的时间对象名称。在调用该cmdlet时需要指定日志及其所在计算机的名称。在上面的脚本中,使用的是本计算机的日志。句点(.)表示当前计算机的快捷方式。
一旦在$Applog日志中创建了到应用程序日志的引用,还需要使用Source属性将ps_script来源指定给该对象,然后使用WriteEntry方法将内容写入到应用程序日志。上面的代码执行后写入系统日志中的新记录如图1所示,在事件查看器中显示的内容图2所示。
图1 写入系统日志中的新记录
图2 在事件查看器中显示的内容
(2)将cmdlet的输出内容保存到日志中
前面在日志中写入字符串也许看起来比较简单,但却有很多深层次的用途。如可以使用WriteToAppLog.ps1将脚本的运行情况及运行是否成功的结果写入事件日志,这对后面的程序排错和调试很有用。
另外还可以使用这种将信息写入到事件日志中的方法来保存PowerShell代码的运行结果。为了能够将WMI的查询结果写入到应用程序日志中,通过记录特定时间在特定计算机中运行的进程,则得到调整性能和增强安全性的第一手资料。创建名为“WriteProcessToAppLog.ps1”的脚本,其代码如下:
$strProcess = Get-WmiObject win32_process |
select-object name | Out-String
if(![system.diagnostics.eventlog]::sourceExists("ps_script"))
{
$applog = [system.diagnostics.eventlog]::CreateEventSource("ps_script","Application")
}
$applog = New-Object system.diagnostics.eventlog("application",".")
$applog.source = "ps_script"
$applog.writeEntry($strProcess)
该脚本使用Get-WmiObject cmdlet对Win32_process类执行基本的WMI查询,这样将会生成一个对象集合,其中包括本机中所有进程的属性和方法信息。为了减少返回的信息数量,可以使用Select-Object并选择需要的名称,这样获得的结果将是自定义的Windows PowerShell对象。为了将信息转换为字符串,需要使用Out-String cmdlet。也可以使用名为“System.Diagnostics.EventLog”的.NET Framework类的WriteEntry方法将包括在$strProcess变量中的类表中的进程名称转换为字符串。
执行后写入的日志如图3所示。
图3 执行后写入的日志
2 搜索事件日志
将事件日志导出为文本、XML或其他格式后,搜索日志的最简单方法是使用Get-EventLog cmdlet。不需要将日志保存为其他格式,而只需要用管道命令将结果传递给其他搜索的cmdlet即可,本节介绍一些技巧,首先创建一个名为“SearchByEventID.ps1”的脚本,其代码如下:
Get-EventLog –LogName system | Where-Object {$_.eventID –eq 1023}
要搜索事件日志,还需要知道EventLogEntry对象中的成员。该对象是名为“System.Diagnostics.EventLogEntry”的对象,并且是标准的.NET Framework类。可以使用Get-Member cmdlet检索表1所示的System.Diagnostics.EventLogEntry对象的属性。
表1 System.Diagnostics.EventLogEntry对象属性
名 称 |
描 述 |
Category |
System.String Category {get;} |
CategoryNumber |
System.Int16 Category {get;} |
Container |
System.ConponementModel.ICotainer Container{get;} |
Data |
System.Byte[] Data {get;} |
entryType |
System.Diagnostics.EventLogEntry EntryType{get;} |
Index |
System.Int32 Index {get;} |
IndexID |
System.Int64 InstanceId {get;} |
MachineName |
System.String MachineName {get;} |
Message |
System.String Message {get;} |
ReplacementStrings |
System.String[] ReplacementStrings {get;} |
Site |
System.String Site {get;} |
Source |
System.String Source {get;} |
TimeGenerated |
System.DateTime TimeGenerated {get;} |
TimeWritten |
System.DateTime TimeWritten {get;} |
UserName |
System.String Source {get;} |
EventID |
System.Object EventID {get=$this.get_EventID() –band 0xFFFF;} |
(1)筛选属性
如果要减少Get-EventLog cmdlet返回的信息数量,可以用Where-Object过滤不需要的对象,事件日志中的常用筛选属性是EventID、Source、Security及Message Text。
(2)选择来源
如果Windows Installer(Windows安装软件,包括适用于32 位Windows操作系统的Windows Installer服务器,以及一个用于存储有关配置和安装信息的新软件包文件格式)出现问题,则可以在事件日志中查找所有来源名为“MsiInstaller”的事件。为此创建一个名为“FindMsiEvent.ps1”脚本查找所有有关Msi安装信息的日志,以在安装错误时解决问题,其代码如下:
Get-EventLog application | where-object {$_.source -like "*Msi*"}
执行结果如图11所示。
图4执行结果
(3)选择严重性
通常情况下用户可能只想看到“错误”级别的事件日志,为此创建一个GetSystemLogError.ps1脚本根据事件的严重性筛选系统日志。其中使用$StrType变量保存要获取的事件日志项的类型名称,然后使用Get-EventLog cmdlet检索系统事件日志,并返回事件日志的对象集合。最后通过管道传递给Where-Object cmdlet过滤,过滤使用脚本中的$_变量值。使用默认视图输出该对象,代码如下:
$strLog = "system"
$strType = "error"
Get-EventLog $strLog | Where-Object {$_.entryType -eq $strType}
执行结果如图5所示。
图5 执行结果
(4)选择消息
搜索日志的另外一种方法是使用正则表达式匹配日志中的消息内容,可以通过-match参数使用Where-Object cmdlet调用正则表达式。
用管道将Get-EventLog cmdlet生成的结果对象传递给Where-Object cmdlet,为此使用自动变量$_,其中保存需要检索Message属性的事件日志项对象。随后使用-match参数配合Where-Object cmdlet查找包括在$strText变量中的字符串,这里搜索的是有关Firebird数据库的所有信息。以下是GetMessage.ps1脚本的代码:
$strLog = "System"
$strText = "Firebird"
Get-EventLog -LogName $strLog | Where-Object {$_.message -match $strText}
执行结果如图6所示。
图6 执行结果
3 总结
本文介绍了通过PowerShell对Windows Vista和Windows Server 2008的事件日志进行管理的操作,包括使用Get-EventLog cmdlet生成可用的事件日志清单、使用同一个cmdlet写入、搜索不同的事件日志。
作者: 付海军
版权:本文版权归作者所有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://txj.shell.tor.hu/