powershellevent-log

Get a list of available `-LogName` and `-Source` for `Write-EventLog` without the administrator privilege


Background

PS C:\> try { Write-EventLog -LogName "Application" -Source 'NewApplication' -EventId "400" -Message "TEST MESSAGE" } catch { $_ | Format-List * -Force | Out-String }


PSMessageDetails      :
Exception             : System.Security.SecurityException: The source was not found, but some or all event logs could not be searched.  Inaccessible logs: Security.
                           at System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly, Boolean wantToCreate)
                           at System.Diagnostics.EventLog.SourceExists(String source, String machineName, Boolean wantToCreate)
                           at Microsoft.PowerShell.Commands.WriteEventLogCommand.BeginProcessing()
                           at System.Management.Automation.Cmdlet.DoBeginProcessing()
                           at System.Management.Automation.CommandProcessorBase.DoBegin()
                        The Zone of the assembly that failed was:
                        MyComputer
TargetObject          :
CategoryInfo          : NotSpecified: (:) [Write-EventLog], SecurityException
FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.WriteEventLogCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}

Problem

So I want to get lists of available -LogName and -Source for the script.

You can get a list of events with Get-EventLog -List or Get-EventLog -LogName <LogName>, but it contains -LogName and -Source that are unavailable for my script. It also contains only the events that are already logged to Event Log (it is not an exhaustive list of available -LogName and -Source).

Question

Is there any way to get the exhaustive list of available -LogName and -Source for Write-EventLog without the administrator privilege?

Edit

For example, you will get the following error when you specify unmatched -LogName and -Source:

PS C:\> Write-EventLog -LogName "Application" -Source "Application Popup" -EventId "1000" -Message "TEST MESSAGE"
Write-EventLog : The source 'Application Popup' is not registered in log 'Application'. (It is registered in log 'System'.) " The Source and Log properties must be matched, or you may set Log to the empty string, and it will automatically be matched to the Source property.
At line:1 char:1
+ Write-EventLog -LogName "Application" -Source "Application Popup" -Ev ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-EventLog], Exception
    + FullyQualifiedErrorId : The source 'Application Popup' is not registered in log 'Application'. (It is registered in log 'System'.) " The Source and Log properties must be matched, or you may set Log to the empty string, and it will automatically be matched to the Source property.,Microsoft.PowerShell.Commands.WriteEventLogCommand

But when you set an empty string to -LogName according to the error above, you will get another error like this:

PS C:\> Write-EventLog -LogName "" -Source "Application Popup" -EventId "1000" -Message "TEST MESSAGE"
Write-EventLog : Cannot validate argument on parameter 'LogName'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At line:1 char:25
+ Write-EventLog -LogName "" -Source "Application Popup" -EventId "1000 ...
+                         ~~
    + CategoryInfo          : InvalidData: (:) [Write-EventLog], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.WriteEventLogCommand

Solution

  • You can get the list of log names that Get-EventLog can target as follows:

    $logNames = 
      (Get-EventLog -LogName *).Log
    

    Source names can be discovered via the registry, on a per-log basis:

    # Initialize an ordered hashtable that will contain log names as keys 
    # and the corresponding source names as the values.
    $sourcesPerLog =  [ordered] @{}
    
    # Loop over all log names and find the names of all sources registered
    # for that log.
    # Exclude the 'Security' log, because its sources cannot be queried without
    # elevation; however, given that this log is "for system use only", that shouldn't be a problem.
    Get-EventLog -LogName * | 
      Where-Object Log -ne Security | 
      ForEach-Object {
        $logName = $_.Log
        $sourcesPerLog[$logName] = 
          (Get-ChildItem HKLM:\System\CurrentControlSet\Services\EventLog\$logName).PSChildName
      }
    
    # Output for diagnostic purposes.
    $sourcesPerLog
    

    Sample output:

    Name                           Value
    ----                           -----
    Application                    {.NET Runtime, .NET Runtime Optimization Service, Application, Application Error...}
    HardwareEvents
    Internet Explorer
    Key Management Service         KmsRequests
    OAlerts                        Microsoft Office 16 Alerts
    System                         {ACPI, AFD, Application Management Group Policy, Application Popup...}
    Windows PowerShell             PowerShell
    

    Note:


    Caveat:

    Get-EventLog uses a Win32 API that is deprecated. The results may not be accurate. Use the Get-WinEvent cmdlet instead.