I find the ability of the Get-WinEvent cmdlet to read event logs absolutely awesome. But I also find the lack of other commands that match the WinEvent noun disturbing π
Get-Command -Noun WinEvent
To fix this, I propose to add two functions to your toolbox to either enable or disable eventlogs.
I’ve made the code compatible with version 2.0 so that you can use the code everywhere.
But there are also some limitations. The functions are designed to be used locally. I mean that that they don’t support natively credentials and remoting like the original Get-WinEvent cmdlet does.
Note also that you must have admin privileges to enable or disable a log.
#Requires -version 2.0 Function Enable-WinEvent { <# .SYNOPSIS Enable event logs by name .DESCRIPTION Enable event logs by their exact full name .PARAMETER PassThru Switch to allow System.Diagnostics.Eventing.Reader.EventLogConfiguration objects to flow into the pipeline .PARAMETER LogName Array of eventlog names .EXAMPLE Enable-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL","Microsoft-Windows-AppLocker/MSI and Script" -PassThru .EXAMPLE Get-WinEvent -ListLog * | Where {$_.LogName -Match "Applocker" } | Enable-WinEvent -Verbose .EXAMPLE Get-WinEvent -ListLog * | Where {$_.LogName -Match "Applocker" } | Enable-WinEvent -Passthru | Format-Table -Property LogMode,MaximumSizeInBytes,RecordCount,LogName,isEnabled -AutoSize .NOTES You cannot enable or disable a classic log. A warning will be issued if you do. #> [cmdletbinding()] Param( [Parameter(Mandatory=$true,ValueFromPipeLine=$true,ValueFromPipelineByPropertyName=$true)] [Alias('Log')] [system.string[]]$LogName, [Switch]$Passthru ) Begin{ $allLogs = Get-WinEvent -ListLog * -Force -ErrorAction SilentlyContinue } Process { $LogName | ForEach-Object -Process { $log = $wineventlog = $null $log = $_ # Get rich object that maps the logname $wineventlog = $allLogs | Where { $_.LogName -EQ $log} if ($wineventlog) { if ($wineventlog.isClassicLog) { Write-Warning "Cannot enable classic log: $_" } else { try { $wineventlog.set_IsEnabled($true) | Out-Null $wineventlog.SaveChanges() Write-Verbose -Message "Successfully enabled log $($wineventlog.logname)" if ($Passthru) { $wineventlog } } catch { Write-Warning -Message "Failed to enable $($wineventlog.logname) because $($_.Exception.Message)" } } } else { Write-Warning "Cannot find a log named $_" } } } End {} } Function Disable-WinEvent { <# .SYNOPSIS Disable event logs by name .DESCRIPTION Disable event logs by their exact full name .PARAMETER PassThru Switch to allow System.Diagnostics.Eventing.Reader.EventLogConfiguration objects to flow into the pipeline .PARAMETER LogName Array of eventlog names .EXAMPLE Disable-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL","Microsoft-Windows-AppLocker/MSI and Script" -PassThru .EXAMPLE Get-WinEvent -ListLog * | Where {$_.LogName -Match "Applocker" } | Disable-WinEvent -Verbose .EXAMPLE Get-WinEvent -ListLog * | Where {$_.LogName -Match "Applocker" } | Disable-WinEvent -Passthru | Format-Table -Property LogMode,MaximumSizeInBytes,RecordCount,LogName,isEnabled -AutoSize .NOTES You cannot enable or disable a classic log. A warning will be issued if you do. #> [cmdletbinding()] Param( [Parameter(Mandatory=$true,ValueFromPipeLine=$true,ValueFromPipelineByPropertyName=$true)] [Alias('Log')] [system.string[]]$LogName, [Switch]$Passthru ) Begin{ $allLogs = Get-WinEvent -ListLog * -Force -ErrorAction SilentlyContinue } Process { $LogName | ForEach-Object -Process { $log = $wineventlog = $null $log = $_ # Get rich object that maps the logname $wineventlog = $allLogs | Where { $_.LogName -EQ $log} if ($wineventlog) { if ($wineventlog.isClassicLog) { Write-Warning "Cannot disable classic log: $_" } else { try { $wineventlog.set_IsEnabled($false) | Out-Null $wineventlog.SaveChanges() Write-Verbose -Message "Successfully disabled log $($wineventlog.logname)" if ($Passthru) { $wineventlog } } catch { Write-Warning -Message "Failed to enable $($wineventlog.logname) because $($_.Exception.Message)" } } } else { Write-Warning "Cannot find a log named $log" } } } End {} }
Let’s see the functions in action.
- Disable two Applocker logs
Disable-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL","Microsoft-Windows-AppLocker/MSI and Script" -PassThru
- Display the Applocker logs and see which ones are enabled
Get-WinEvent -ListLog * | Where LogName -Match "Applocker" | Format-Table -Property LogMode,MaximumSizeInBytes,RecordCount,LogName,isEnabled -AutoSize
- Let’s enable all applocker logs and use the passthru switch to pass directly the log to Format-Table cmdlet to report their status
Get-WinEvent -ListLog * | Where {$_.LogName -Match "Applocker" } | Enable-WinEvent -Passthru | Format-Table -Property LogMode,MaximumSizeInBytes,RecordCount,LogName,isEnabled -AutoSize
That’s all folks! May the force be with you π
Finally! I look for this solution I think more than 3 years. BIG THAAAANKS!!!!!!!!!!