Create Event Log in Sub Directory under Applications and Settings Logs
Asked Answered
S

2

9

I have been searching for ages to find a way to create a number of separate event logs under a sub directory of Applications and Services Logs, in the same way that there is a subdirectory Microsoft then it has a subdirectory Windows then various other directories with the App log in.

  • Applications and Services\Microsoft\Windows\All-User-Install-Agents
  • Applications and Services\Microsoft\Windows\AppHost
  • ...

I would like to create something like the following

  • Applications and Services\My Company\Application 1
  • Applications and Services\My Company\Application 2
  • Applications and Services\My Company\Application 3

All the samples I have come across only allow you to create the log directly under the Applications and Services directory and not make a sub directory.

Thanks

Schnauzer answered 13/10, 2014 at 8:43 Comment(0)
A
1

I was struggling to get the subfolder piece working as well, as I would like to have a structure like:

- Application and Services Logs
-- Company Name
--- Application 1
---- ApplicationLog
--- Application 2
---- SecurityLog
---- OperationalLog

I could not find any way to do this directly using C or PowerShell, however after doing some trial and error with registry keys and the documentation provided at https://learn.microsoft.com/en-us/windows/desktop/eventlog/eventlog-key I finally got it to work.

It seems that you need to create keys at HKLM\Software\Microsoft\Windows\CurrentVersion\WINEVT\Channels, where the primary registry key name is key to the 'folder' structure. a '-' is seen as a deeper structure. So for example: CompanyName\Application\Log, should be a key named CompanyName-Application-Log.

Below is an example script to do this using PowerShell:

# Create the eventlog (in a subfolder structure)
# Params()
$PrimaryEventKey = 'Company'
$ApplicationName = 'Application'
$LogName = 'NewLog'

# Vars()
$primarylocation = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\WINEVT\Channels'
$LogName = $PrimaryEventKey + '-' + $ApplicationName + '-' + $LogName
$EventRoot = (Join-Path $primarylocation $LogName)

if (!(Test-Path $EventRoot)) {
New-Item -Path ($secondarylocation + '\' + $Logname)
New-ItemProperty -Path ($secondarylocation + '\' + $Logname) -Name providerGuid -PropertyType String -Value "{$($GUID)}"

New-Item -Path $EventRoot
New-ItemProperty -Path $EventRoot -Name Enabled -PropertyType DWord -Value 1
New-ItemProperty -Path $EventRoot -Name Type -PropertyType DWord -Value 1
New-ItemProperty -Path $EventRoot -Name Isolation -PropertyType DWord -Value 0
New-ItemProperty -Path $EventRoot -Name RestrictGuestAccess -PropertyType String -Value 1
New-ItemProperty -Path $EventRoot -Name OwningPublisher -PropertyType String -Value "{$($GUID)}"

    # See https://learn.microsoft.com/en-us/windows/desktop/eventlog/eventlog-key for documentation on the ChannelAccess or or RestrictGuestAccess (see: RestrictGuestAccess / Isolation)
}
else {
    Write-Warning 'Event Log (Key) Already exists in registry'
}

# Write into the event log (Example)
$eventType = ([System.Diagnostics.EventLogEntryType]::Information)
$evt = New-Object System.Diagnostics.EventLog($LogName)
$evt.Source = "SomeSource"
$evt.WriteEntry("random message", $eventType, 60001)
Alvardo answered 4/9, 2018 at 13:31 Comment(2)
please provide a tested code.. or at least a full code.. :( i guess $secondaryLocation is HKLM:\SYSTEM\CurrentControlSet\Services\EventLog ?? this is not working eitherDermatophyte
Hmm, I was glad to see someone solved this without .NET ... The idea is nice, but does not work at all. Have you ever tried a copy/paste of this into PowerShell yourself? :(Kelbee
D
1

If still needed I figured out a good working solution for me, though it's utilizing Powershell rather than C#. You need 2 Steps:

  1. Create the log itself
  2. Create (if needed) Event Sources

Here my Code for creating a sub-folder located Custom EventLog:

function New-WindowsCustomLog
{
    <#
    .SYNOPSIS
        Create a custom Eventlog

    .DESCRIPTION
        This function will create a new eventlog located under 'Application and Serviceprotocolls' using a company subfolder and if needed additional functional subfolder.

    .PARAMETER PrimaryKey
        Mostly used for the company name.

    .PARAMETER ApplicationName
        Application name.

    .PARAMETER ApplicationFunction
        Optional: If you need to create another subfolder for functions.

    .PARAMETER LogName
        The name of the Log itself.

    .PARAMETER ProviderGUID
        Provider/Publisher GUID, if you don't have one, create by using New-GUID enter without {} around.

    .EXAMPLE
                New-WindowsCustomLog -PrimaryKey 'My Company' -ApplicationName 'My Cool Tool' -LogName 'Operational' -ProviderGUID '{49ab7419-7113-40d1-8910-8be1c3f96d21}'

    .EXAMPLE
                New-WindowsCustomLog -PrimaryKey 'My Company' -ApplicationName 'My Cool Tool' -ApplicationFunction 'Incoming' -LogName 'Requests' -ProviderGUID '{49ab7419-7113-40d1-8910-8be1c3f96d21}'
                New-WindowsCustomLog -PrimaryKey 'My Company' -ApplicationName 'My Cool Tool' -ApplicationFunction 'Outgoing' -LogName 'Requests' -ProviderGUID '{49ab7419-7113-40d1-8910-8be1c3f96d21}'

    #>
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 0)]
        [string]$PrimaryKey,
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [string]$ApplicationName,
        [Parameter(Position = 2)]
        [string]$ApplicationFunction,
        [Parameter(Mandatory = $true,
                   Position = 3)]
        [string]$LogName,
        [Parameter(Mandatory = $true,
                   Position = 4)]
        [String]$ProviderGUID
    )
    $publisherGuid = "{$($ProviderGUID)}"
    $primaryLocation = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\WINEVT\Channels'
    $secondaryLocation = 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application'
    #$thirdLocation = 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\System' # needed for driver purposes
    $publisher = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Publishers'

    if (-not ([string]::IsNullOrEmpty($ApplicationFunction)))
    {
        $primaryLogName = $PrimaryKey + '-' + $ApplicationName + '-' + $ApplicationFunction + '§' + $LogName
        $secondaryLogName = $PrimaryKey + '-' + $ApplicationName + '-' + $ApplicationFunction
    }
    else
    {
        $primaryLogName = $PrimaryKey + '-' + $ApplicationName + '-' + '§' + $LogName
        $primaryLogNameSlash = $primaryLogName.Replace("§", "/")
        $secondaryLogName = $PrimaryKey + '-' + $ApplicationName
    }
    $evtxFilePath = "%SystemRoot%\System32\Winevt\Logs\$($secondaryLogName)%4$($LogName).evtx"
    $primaryEventRoot = Join-Path -Path $primaryLocation -ChildPath $primaryLogName
    $secondaryEventRoot = Join-Path -Path $secondaryLocation -ChildPath $secondaryLogName
    #$thirdEventRoot = Join-Path -Path $thirdLocation -ChildPath $secondaryLogName # needed for driver purposes
    $publisherEventRoot = Join-Path -Path $publisher -ChildPath $publisherGuid
    if (-not (Test-Path $primaryLogNameSlash)) #$primaryEventRoot.Replace("§", "/")))
    {
        &reg add $primaryLogNameSlash.Replace(":", "") # used because I wasn't able to write a real / to registry key name by CMDLET
        New-ItemProperty -Path $primaryLogNameSlash -Name 'Enabled' -PropertyType DWord -Value 1
        New-ItemProperty -Path $primaryLogNameSlash -Name 'Type' -PropertyType DWord -Value 1
        New-ItemProperty -Path $primaryLogNameSlash -Name 'Isolation' -PropertyType DWord -Value 0
        New-ItemProperty -Path $primaryLogNameSlash -Name 'RestrictGuestAccess' -PropertyType String -Value "1"
        New-ItemProperty -Path $primaryLogNameSlash -Name 'OwningPublisher' -PropertyType String -Value $publisherGuid
    }
    if (-not (Test-Path $secondaryEventRoot))
    {
        New-Item -Path $secondaryEventRoot
        New-ItemProperty -Path $secondaryEventRoot -Name 'ProviderGuid' -PropertyType String -Value $publisherGuid
        New-ItemProperty -Path $secondaryEventRoot -Name 'File' -PropertyType ExpandString -Value $evtxFilePath
    }
    <# needed for driver purposes
    if (-not (Test-Path $thirdEventRoot))
    {
        New-Item -Path $thirdEventRoot
        New-ItemProperty -Path $thirdEventRoot -Name 'ProviderGuid' -PropertyType String -Value $publisherGuid
        #New-ItemProperty -Path $thirdEventRoot -Name 'EventMessageFile' -PropertyType ExpandString -Value $evtMessageFile
    }
    #>
    if (-not (Test-Path $publisherEventRoot))
    {
        New-Item -Path $publisherEventRoot -Value $secondaryLogName
        New-ItemProperty -Path $publisherEventRoot -Name 'Enabled' -PropertyType DWord -Value 1
        $channelReference = Join-Path -Path $publisherEventRoot -ChildPath "ChannelReference"
        New-Item -Path $channelReference
        New-ItemProperty -Path $channelReference -Name 'Count' -PropertyType DWord -Value 1
        $reference0 = Join-Path -Path $channelReference -ChildPath "0"
        New-Item -Path $reference0 -Value $primaryLogName.Replace("§", "/")
        New-ItemProperty -Path $reference0 -Name 'Flags' -PropertyType DWord -Value 0
        New-ItemProperty -Path $reference0 -Name 'Id' -PropertyType DWord -Value 16
    }
    return $primaryLogNameSlash
}

Next is a simple function to create the Event Source (if Log is available and source is not already registered):

function New-WindowsEventSource
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 0)]
        [ValidateScript({ [System.Diagnostics.EventLog]::Exists($_) })]
        [string]$EventLogName,
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [ValidateScript({ (-not ([System.Diagnostics.EventLog]::SourceExists($_))) })]
        [string]$EventSourceName
    )
    [System.Diagnostics.EventLog]::CreateEventSource($EventSourceName, $EventLogName)
}

And here is how to create a source / fill the EventLog:

New-WindowsEventSource -EventLogName "My Company-My Cool Tool-Incoming/Requests" -EventSourceName "webbrowser"

Write-EventLog -LogName "My Company-My Cool Tool-Incoming/Requests" -Source "webbrowser" -EntryType Information -EventId 100 -Message "New request received."

Kind regards and happy coding

Disherison answered 8/4, 2020 at 12:11 Comment(2)
Hmm, I was glad to see someone solved this without .NET ... But I get all kinds of errors; pastebin.com/DKxdWQpYKelbee
Huh. Is creating registry keys directly still the only way to do this in 2024? I tried to do this with New-EventLog and Write-EventLog, but the events always show up in the "Applications" sections, and not in "Applications and Services Logs"Applegate

© 2022 - 2024 — McMap. All rights reserved.