Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

The CIM-ple way with PowerShell and Event Logs

Posted on June 17, 2016

I'm always on the lookout for new ways to do things. Often I'm trying to find a way to create something that is easy to use without requiring a lot of PowerShell scripting.  I also like using the final result as teaching aids so even if you don't need the end product, I hope you'll pick up a trick or two that you can use in your own scripting projects. The task I had in mind today is a better way to get event log information. Not the events themselves, but rather the event log file. How many entries are in it? How big is it? How much of the configured log is being used? Here's what I came up with.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

We have always had the Get-Eventlog cmdlet which will provide some of this information using the -List parameter.

Listing with Get-Eventlog

There is a bit more to each object and you could use a PowerShell expression with Select-Object to get the desired result. You could also write a function to simplify the process. But if you have to go that route, I say find a way to use CIM or PowerShell remoting. So much of remote access in PowerShell is done over legacy protocols and I believe we should strive to do more over WsMan. Because the event log files are exposed via WMI through the Win32_NTEventLogFile, we can use Get-CimInstance to retrieve them.

Listing with Get-CimInstance

Yes, the output is different. But by looking at the properties I can create a function to make it easier to query and write a custom object to the pipeline with more relevant information.

Using a PowerShell function

In my testing this is also much faster than using Get-Eventlog.  Want to know how I did this and how it works? Grab a copy of the script file from GitHub.

The function includes complete help and examples and I've attempted to document with internal comments throughout. But let me touch on a few highlights.

First, because the function is essentially a wrapper for Get-CimInstance, I wanted to be able to use both computer names and CimSessions. You'll notice in the Parameters section that I'm using 2 parameter sets.  You'll see that both sets are configured to accept value from pipeline.  This works because when PowerShell processes incoming, it detects the object type and selects the appropriate parameter set.

My function also includes a few other parameters used by Get-CimInstance like -Filter. Anything that is specified when the command is executed becomes a part of the built-in variable $PSBoundParameters, which is a hashtable. I display it with Write-Verbose which is handy when troubleshooting. The great thing about $PSBoundParameters is that I can splat. The main part of my function splats to Get-CimInstance.

Get-CimInstance @PSBoundParameters | Select $ListProperties

However, this means for other parameters like -Name,  I need to adjust PSBoundParameters because -Name isn't part of Get-CimInstance.

if ($Name) {
     #remove from PSBoundparameters
     $PSBoundParameters.Remove("Name") | Out-Null
     
     $filter = "logfilename = '$Name'"
     Write-Verbose "[BEGIN  ] Adding filter: $filter"
     $PSBoundParameters.Add("Filter",$filter)
         
   }

I can remove the bound parameter, but this doesn't delete the value of $Name. It merely removes it from the hashtable. I can still use the parameter. In this case I'm defining a WMI filter and and adding Filter to $PSBoundParameters because that is a part of Get-CimInstance.

The other thing I've done which I think makes the script easier to read, is to define a set of properties in the Begin block. This keeps the Process block a bit simpler. In my function, I knew I wanted to get certain properties and use certain names. I also wanted to create new properties with some calculated values. For example, I wanted to show a percentage used value: How much of the configured maximum size is being used from the actual file size.

#define a set of Properties to return
   $Properties = @{Name="Computername";Expression={$_.CSName}},
   @{Name="LogName";Expression={$_.LogFileName}},
   "NumberOfRecords",
   @{Name="Path";Expression={$_.Name}},
   @{Name="SizeMB";Expression = {[math]::Round($_.FileSize/1MB,2)}},
   @{Name="MaxSizeMB";Expression = {$_.MaxFileSize/1MB -as [int]}},
   @{Name="PctUsed";Expression= {[math]::Round(($_.FileSize/$_.maxFileSize)*100,2)}},
   "LastModified",
   @{Name="ModifiedAge";Expression={(Get-Date) - $_.LastModified}}

I also combined these techniques. I wanted an option to display a quick list of event logs showing only the log name and number of entries.

if ($ListOnly) {
        #update PSBoundparameters
        #limit Get-CimInstance to only retrieving the required
        #properties which should speed up the query.
        $PSBoundParameters.Add("Property", @("Logfilename","NumberofRecords","CSName"))
        $PSBoundParameters.Remove("ListOnly") | Out-Null

        #define a list properties
        $ListProperties = @{Name="Computername";Expression={$_.CSName}},
        @{Name="LogName";Expression={$_.LogFileName}},
        "NumberOfRecords"
   }

Get-CimInstance supports retrieving only selected properties which can improve performance so I add that to $PSBoundParameters, get rid of the function's parameter and define a collection of properties when using -ListOnly.

List only with Get-EventLogFile

Whenever I have used Get-Eventlog in the past I've usually had to add a step to filter out logs with no entries. So I included that ability in my function. Although I wanted the option to combine this with other parameters.

if ($SkipEmptyLog -And $Name) {
        #update existing filter
        #remove from PSBoundparameters
        $PSBoundParameters.Remove("SkipEmptyLog") | Out-Null
        $filter+= " AND NumberofRecords<>0"
        Write-Verbose "[BEGIN  ] Updating filter: $filter"
        $PSBoundParameters.Filter = $filter
     
   }
   elseif ($SkipEmptyLog) {
       #remove from PSBoundparameters
       $PSBoundParameters.Remove("SkipEmptyLog") | Out-Null

       #create filter to only filter out logs with no records
       $filter+= "NumberofRecords<>0"
       Write-Verbose "[BEGIN  ] Adding filter: $filter"
       $PSBoundParameters.Add("Filter",$filter)
   }

Remember, I'm always thinking about managing at scale and querying multiple servers at once. It might be possible that I want to query for a specific event log on 100 servers and skip any that have 0 entries.

Here are some examples of the function in action.

get-cimsession | get-eventlogfile -Name System | Out-Gridview -Title "System"

I can pipe existing CIM sessions to the command.

System Event Log Data

Or find logs that are full

get-cimsession | get-eventlogfile | Where {$_.PctUsed -ge 100 } | sort PctUsed,Computername -Descending | select Computername,LogName,*Size*,PctUsed | format-table

Getting high usage event logs with PowerShell

Clearly I need to address the Security log on my domain controller!

There are many ways I can think of to use this function. Of course I'd love to hear from you. Does this solve any problems? Did you pick up anything useful? How might you use it? If you encounter any bugs or have upgrade requests, please post them in comments on the GitHub page.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d