Sunday, April 24, 2011

The 2011 Scripting Games Advanced Event 3: Use PowerShell to Query Classic Event and ETL Diagnostic Logs

The 2011 Scripting Games Advanced Event 3: Use PowerShell to Query Classic Event and ETL Diagnostic Logs

My personal script:
http://2011sg.poshcode.org/1011
Average Rating: 4.00 by 2 users.
(Download it)


#
#
# 2011 Scripting Games Advanced Event 3: Use PowerShell to Query Classic Event and ETL Diagnostic Logs
#
# by F.Richard 2011-04
#
#

#Requires -Version 2.0

# Main Program
Param(
[String] $action = "localhost",
[String] $inputfile,
[String] $iNbEvents,
[String] $providername,
[String] $level,
[Int] $id,
[Int] $days,
[String] $logname,
[String] $message
)



# ***********************************************

Function isComputerInADomain {
<#
.SYNOPSIS
Is computer in a domain
.DESCRIPTION
Is computer in a domain. Return $True or $False
.PARAMETER strComputer
Computer name. Default to localhost.
.EXAMPLE
isComputerInADomain
is local machine in a domain ?
.EXAMPLE
isComputerInADomain mycomputer
is mycomputer in a domain ?
#>
Param ([string] $strComputer)
$strComputer = $(if ($strComputer) {$strComputer} else {Get-Content ENV:COMPUTERNAME})
if ((Get-WmiObject -ComputerName $strComputer Win32_ComputerSystem).PartOfDomain -eq $true) {
return $true
} else {
return $false
}
}

# ***********************************************

Function GetUserDomainDNS {
<#
.SYNOPSIS
return user domain name in DNS format ex: domain.net
.DESCRIPTION
return user domain name in DNS format ex: domain.net
.EXAMPLE
GetUserDomainDNS
return user domain name ex: domain.net
#>
[string] $strDomainDNS = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
Return $strDomainDNS
}

# ***********************************************

Function GetComputerDomainDNS {
<#
.SYNOPSIS
return local computer domain name in DNS format ex: domain.net
.DESCRIPTION
return local computer domain name in DNS format ex: domain.net
.EXAMPLE
GetComputerDomainDNS
return local computer domain name ex: domain.net
#>
[string] $strDomainDNS = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain().Name
Return $strDomainDNS
}

# ***********************************************

# GetDomainDN
# get Domain name in DNS format ex: domain.net
#
Function GetDomainDN {
<#
.SYNOPSIS
return domain name in Distinguished Name format ex: DC=DOMAIN,DC=NET
.DESCRIPTION
from domain name DNS format domain.net to
return domain name in Distinguished Name format ex: DC=DOMAIN,DC=NET
.PARAMETER strDomainDNS
Domain name in DNS format. Ex: domain.net
.EXAMPLE
GetDomainDN domain.net
return DC=DOMAIN,DC=NET
.EXAMPLE
GetDomainDN -strDomainDNS domain.net
return DC=DOMAIN,DC=NET
#>
Param ([string] $strDomainDNS)
$strDomainDN = "DC=" + $strDomainDNS -replace "\.",",DC="
Return $strDomainDN
}

# ***********************************************

Function SearchAD {
<#
.SYNOPSIS
return AD query
.DESCRIPTION
return AD query
.PARAMETER options
Hashtable
.EXAMPLE
$hashSearchAD = @{ }
$hashSearchAD["strFilter"] = "(objectCategory=computer)"
$hashSearchAD["strSearchScope"] = "Subtree"
$hashSearchAD["colAttributes"] = "name"
$hashSearchAD["strBaseDN"] = "DC=DOMAIN,DC=NET"
searchAD $hashSearchAD
#>
Param ([hashtable] $options)
$strFilter = $(if ($options.ContainsKey("strFilter")) {$options["strFilter"]} else {""}) # ex: '(objectCategory=computer)'
$strSearchScope = $(if ($options.ContainsKey("strSearchScope")) {$options["strSearchScope"]} else {"Subtree"}) # Base, OneLevel or Subtree
$colAttributes = $(if ($options.ContainsKey("colAttributes")) {$options["colAttributes"]} else {""}) # ex: '"name", "jobTitle", "telephoneNumber"
$strBaseDN = $(if ($options.ContainsKey("strBaseDN")) {$options["strBaseDN"]} else {""}) # ex: DC=Domain,DC=NET

$strBase = New-Object System.DirectoryServices.DirectoryEntry ("LDAP://" + $strBaseDN)
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $strBase
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = $strSearchScope
Foreach ($attribute in $colAttributes){$objSearcher.PropertiesToLoad.Add($attribute)}

$dtResult = New-Object "System.Data.DataTable"
$dtResult = $objSearcher.FindAll() # .FindOne() .FindAll()
#Write-host "count:" $dtResult.count
return $dtResult
}

# ***********************************************

Function TestFile {
<#
.SYNOPSIS
Test if file exist
.DESCRIPTION
Test if file strFilename exist
Then test if file exist in strCurDir\strFilename path
Return filename path
.PARAMETER strFilename
filename to test
.PARAMETER strCurDir
directory to test filename if not in current directory
.EXAMPLE
TestFile -strFilename abcdefghijkl.txt
return
ERROR: file abcdefghijkl.txt NOT exist
ERROR: file D:\Datas\Dev\abcdefghijkl.txt NOT exist
.EXAMPLE
TestFile -strFilename regedit.exe -strCurDir C:\WINDOWS
return C:\WINDOWS\regedit.exe
#>
Param(
[String] $strFilename,
[String] $strCurDir
)
if ($strFilename) {
$strCurDir = $(if ($strCurDir) {$strCurDir} else {if ($MyInvocation.MyCommand.CommandType -eq "Function") {(Get-Location).Path} else {Split-Path -parent $MyInvocation.MyCommand.Path} })
If ((Test-Path("$strFilename")) -eq $False){
If ($strFilename.ToUpper().Contains($strCurDir.ToUpper()) ) {
Write-Host "ERROR: file $strFilename NOT exist"
return
} Else {
If ((Test-Path("$strCurDir\$strFilename")) -eq $False){
Write-Host "ERROR: file $strFilename NOT exist"
Write-Host "ERROR: file $strCurDir\$strFilename NOT exist"
return
} Else {
$strFilename = "$strCurDir\$strFilename"
}
}
}
return $strFilename
}
}


# ***********************************************

Function GetFileIntoArr {
<#
.SYNOPSIS
Import File into an array
.DESCRIPTION
Import File into an array
.PARAMETER strFilename
filename to import
.PARAMETER strCurDir
directory to test filename if not in current directory
.PARAMETER arrFile
array where file is imported
.PARAMETER strComment
1st line character for comment line (default: #)
.EXAMPLE
[Array] $arrContent = @( )
GetFileIntoArr -strFilename .\content.txt -arrFile ([Ref]$arrContent)
return
#>
Param(
[String] $strFilename,
[String] $strCurDir,
[Ref]$arrFile,
[String] $strComment
)
$strComment = $(if ($strComment) {$strComment} else {"#"})
$strCurDir = $(if ($strCurDir) {$strCurDir} else {if ($MyInvocation.MyCommand.CommandType -eq "Function") {(Get-Location).Path} else {Split-Path -parent $MyInvocation.MyCommand.Path} })

$retFilename = TestFile -strFilename $strFilename -strCurDir $strCurDir
if ($retFilename) {
$Content = Get-Content "$retFilename"
Foreach ($line in $Content) {
$comment = $False
If ($line.Trim().length -gt 0) { # take only line with data and without # at begininng of the line
# if we do not want to use comment
If ($strComment -eq "#") {
If ($line.substring(0,1) -eq "#") {
$comment = $True
}
}
If ($comment -eq $False) {
# Get Search & Replace
$arrFile.Value += $line.Trim()
}
}
}
return $True
} else {
return $False
}
}

# ***********************************************

Function GetADComputerToArray {
<#
.SYNOPSIS
return AD Computer query to array
.DESCRIPTION
return AD Computer query to array
.PARAMETER strDomainDN
Domain name in DN format. Default: Computer Domain Name ex: DC=DOMAIN,DC=NET
.PARAMETER strFilter
Computer AD filter. Default: (objectCategory=computer)
.PARAMETER strSearchScope
Domain name in DNS format. Default: Subtree
.PARAMETER colAttributes
Attributes to get. Default: name
.EXAMPLE
[Array] $arrComputers = @( )
GetADComputerToArray -array ([Ref]$arrComputers)
#>
Param(
[Ref]$array,
[String] $strDomainDN,
[String] $strFilter,
[String] $strSearchScope,
[String] $colAttributes
)
$strDomainDN = $(if ($strDomainDN) {$strDomainDN} else {GetDomainDN -strDomainDNS (GetComputerDomainDNS)})
$strFilter = $(if ($strFilter) {$strFilter} else {'(objectCategory=computer)'})
$strSearchScope = $(if ($strSearchScope) {$strSearchScope} else {"Subtree"})
$colAttributes = $(if ($colAttributes) {$colAttributes} else {"name"})
$hashSearchAD = @{ }
$hashSearchAD["strFilter"] = $strFilter
$hashSearchAD["strSearchScope"] = $strSearchScope # Base, OneLevel or Subtree
$hashSearchAD["colAttributes"] = $colAttributes # ex: '"name", "jobTitle", "telephoneNumber"
$hashSearchAD["strBaseDN"] = $strDomainDN
$dtResult = SearchAD($hashSearchAD)
If ($dtResult -ne $Null) {
Foreach ($row in $dtResult){
If ($row.GetType().Name -eq "Int32") {
} else {
$result = $row.GetDirectoryEntry()
$array.Value += $result.Name
Write-Host $result.Name
}
}
return $True
} else {
return $False
}
}

# ***********************************************



Function Get-AdvEvent3 {
<#
.SYNOPSIS
2011 Scripting Games Advanced Event 3
.DESCRIPTION
2011 Scripting Games Advanced Event 3
Use PowerShell to Query Classic Event and ETL Diagnostic Logs
.PARAMETER action
action : ad / file / localhost
.PARAMETER inputfile
inputfile filename for file option
.PARAMETER iNbEvents
number max of events to display ex: 1, 5 ...
.PARAMETER providername
provider name ex: "Microsoft-Windows-Diagnostics-Performance"
.PARAMETER level
level of severity ex: 1, 2 ...
0 = LogAlways
1 = Critical
2 = Error
3 = Warning
4 = Informational
5 = Verbose
.PARAMETER id
event id ex: 100, 247 ...
.PARAMETER days
get event in last days ex: 2 for 2 last days
.PARAMETER logname
log name ex: "Microsoft-Windows-Diagnostics-Performance/Operational"
.PARAMETER message
message ex: "resolution"
.EXAMPLE
Get-AdvEvent3
Get process module version for AD query computers
.EXAMPLE
Get-AdvEvent3 ad
Get event query for local computer
.EXAMPLE
Get-AdvEvent3 file filename.txt
Get event query for local computer
.EXAMPLE
Get-AdvEvent3 -level 1 -message "resolution" -days 5
get all event with severity 1 critical and message containing "resolution" in last 5 days
#>
Param(
[String] $action = "localhost",
[String] $inputfile,
[String] $iNbEvents,
[String] $providername,
[String] $level,
[Int] $id,
[Int] $days,
[String] $logname,
[String] $message
)
$iNbEvents = $(if ($iNbEvents) {$iNbEvents} else { 1 })
$providername = $(if ($providername) {$providername} else {""})
$level = $(if ($level) {$level} else { "" })
$id = $(if ($id) {$id} else {""})
$logname = $(if ($logname) {$logname} else {""})
$message = $(if ($message) {$message} else {""})
$date = $(if ($days) {[DateTime]::Now.AddDays(- $days).Date} else {[datetime]::today})


# local computername
$computername = (Get-Content ENV:COMPUTERNAME)
[Array] $arrComputers = @( )
# Default action = localhost
switch($action) {
# localhost
"localhost" {
$arrComputers += $computername
}

# AD Query
"ad" {
if(isComputerInADomain) {
# AD query but only Servers
GetADComputerToArray -array ([Ref]$arrComputers) -strFilter "(&(objectcategory=computer)(|(operatingsystem=Windows 2000 Server)(operatingsystem=Windows Server*))) "
} else {
Write-Host "ERROR: $computername is NOT in a domain. You cound not use switch $action"
return
}
}

# File content
"file" {
if ($inputfile) {
if (!(GetFileIntoArr -strFilename $inputfile -arrFile ([Ref]$arrComputers))) {
return
}
} else {
Write-Host "ERROR: With action $action switch you need a filename.txt as second parameter inputfile"
return
}
}

# Others actions = Help
Default {
get-help Get-AdvEvent3 -full
return
}
}

$string=""
Foreach ($computer in $arrComputers) {
Write-Output $string.PadRight(80,"-")
Write-Output "Computername: $computer"
# Event Enabled and writed today
$objEventsList = Get-WinEvent -ComputerName $computer -ListLog * -ErrorAction SilentlyContinue | where-object { $_.IsEnabled -eq "True" -and $_.recordcount -and $_.lastwritetime -gt $date}
[Array] $arrObj = @( )
Foreach($objEvents in $objEventsList) {
# Get Events and filter with parameter given
$objCurEvents = Get-WinEvent -ComputerName $computer -LogName $objEvents.LogName -MaxEvents $iNbEvents -ErrorAction SilentlyContinue | where-object { $_.TimeCreated -gt $date}
if ( $logname -ne "") {
$objCurEvents = $objCurEvents | Where-Object { $_.LogName -eq $logname }
}
if ($providername -ne "") {
$objCurEvents = $objCurEvents | Where-Object { $_.ProviderName -eq $providername }
}
if ($id -ne "") {
$objCurEvents = $objCurEvents | Where-Object { $_.Id -eq $id }
}
if ($message -ne "") {
if (!$objCurEvents.message.isNull) {
$objCurEvents = $objCurEvents | Where-Object { $_.Message.Contains($message) }
}
}
if ($level -ne "") {
$objCurEvents = $objCurEvents | Where-Object { $_.Level -eq $level }
}

if ($objCurEvents) {
foreach ($objCurEvent in $objCurEvents) {
$obj = New-Object PSObject
$obj | Add-Member -MemberType noteproperty -Name "TimeCreated" -Value $objCurEvent.TimeCreated
$obj | Add-Member -MemberType noteproperty -Name "ProviderName" -Value $objCurEvent.ProviderName
$obj | Add-Member -MemberType noteproperty -Name "Id" -Value $objCurEvent.Id
$obj | Add-Member -MemberType noteproperty -Name "Message" -Value $objCurEvent.Message
$obj | Add-Member -MemberType noteproperty -Name "LogName" -Value $objCurEvent.LogName
if ($level -ne "") {
$obj | Add-Member -MemberType noteproperty -Name "Level" -Value $objCurEvent.Level
}

$arrObj += $obj
}
}
}

$arrObj | Format-Table
}

}


# ***********************************************

# Main program

Get-AdvEvent3 -action $action -inputfile $inputfile -iNbEvents $iNbEvents -providername $providername -level $level -id $id -days $days -logname $logname -message $message

No comments: