The Eventlog Trigger

The Eventlog trigger allows you to start an application or a PowerShell script for a specific Eventlog entry. This blog describes the automated creation of such Scheduled Tasks with PowerShell and the possibilities to use such a task as a service replacement. Such a script can also always be started with system rights or as a "Network Service" (in this case the permissions of the computer are used for the network access). In the end, a small write access to an event log is sufficient. This can be created by the user.

New-EventLog -LogName 'MyEventlog' -Source 'powershell.exe'

As a rule, a user may write to such a log. But of course write access can only be allowed for certain users and groups. For this I found the following blog. But there are also other possibilities.

https://blog.backslasher.net/event-log-permissions-with-scripts.html

 Writing to this Evetlog can now also be done with PowerShell, for example

Write-EventLog -LogName 'MyEventlog' -Source 'powershell.exe' -EventId 100 -Message "<Publish>Testdata</Publish>"

 This would then trigger such a task. Unfortunately, there is a way to set up this task with the PowerShell CmdLets. However, I found a way in an article how to do this with COM.

https://stackoverflow.com/questions/42801733/creating-a-scheduled-task-which-uses-a-specific-event-log-entry-as-a-trigger

What is missing here is the possibility to pass parameters like the EventID or the event content to your script. After some attempts I could realize this with "$Trigger.ValueQueries.Create".  In the call only the element has to be passed as parameter: -eventChannel $(eventChannel) -eventData $(eventData) -eventSeverity $(eventSeverity) -eventRecordID $(eventRecordID)

This allows me to trigger an event and thus a task by a user and to give the message of the event a command. For example "Format c:\" to enable corresponding commands with the corresponding rights ;-) 

In the following the script, with which such a task can be created

  function New-ScheduledEventtriggerTask{
    <#
        .SYNOPSIS
        Automatic creation of a Scheduled Task as an Event Trigger

        .DESCRIPTION
        This comdlet installs a scheduled task with a PowerShell script that is triggered by an event log entry. 
        The basic data of the event is passed to the script. The script can still be started with extended privileges 
        under the Network Service or Local System account.The advantage is that a kind of service can be created in a 
        simple way.

        .PARAMETER TaskName
        Name of the event log

        .PARAMETER Logname

        .PARAMETER EventID
        Eventid to be triggered on

        .PARAMETER PowerShellExePath
        64 Bit or 32 Bit PowerShell Path. The default is 'C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe'

        .PARAMETER PowerShellScriptPath
        Path to your script

        .PARAMETER Runlevel
        TASK_RUNLEVEL_LUA = run with minimal rights, TASK_RUNLEVEL_HIGHEST = run with highest previleges

        .PARAMETER TaskAccount
        No play stuff! 'Network Service' or 'Local System'

        .PARAMETER DisableTime
        Time "yyyy-MM-dd'T'HH:mm:ss" at which the task is to be deactivated. If $null then it will never be disabled.

        .EXAMPLE
        #Create a new Event Log
        New-EventLog -LogName 'MyEventlog' -Source 'powershell.exe'

        # Set Permissions
        # maybe not all users should be allowed to write there? This blog hilft         
        # https://blog.backslasher.net/event-log-permissions-with-scripts.html

        #Create a Trgger
        New-ScheduledEventtriggerTask -TaskName MyTask -Logname MyEventLog -EventID 100 -Runlevel TASK_RUNLEVEL_LUA -TaskAccount 'Local System'

        #Put something in your log. Also with user rights
        Write-EventLog -LogName 'MyEventlog' -Source 'powershell.exe' -EventId 100 -Message "<Publish>Testdata</Publish>"
         
        #Then clean up if you don't want the task any more
        Remove-EventLog -LogName  'MyEventlog'
        Unregister-ScheduledTask -TaskName MyTask -Confirm:$false
  
        .NOTES
        The basis for this is a support article. I have greatly expanded everything. Among other things a parameter transfer is now possible.
        https://stackoverflow.com/questions/42801733/creating-a-scheduled-task-which-uses-a-specific-event-log-entry-as-a-trigger

        .LINK
        https://www.andreasnick.com
        https://www.software-virtualisierung.de
    #>


    [CmdletBinding()]
    param(
      
      [Parameter(Mandatory=$true)][string] $TaskName,
      [Parameter(Mandatory=$true)][string] $Logname, #MyEventlog etc.
      [Parameter(Mandatory=$true)][string] $EventID, #MyLog etc.
      
      [System.IO.FileInfo] $PowerShellExePath = 'C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe',
      [System.IO.FileInfo] $PowerShellScriptPath = 'c:\temp\testEvent.ps1',
      
      [ValidateSet('TASK_RUNLEVEL_LUA','TASK_RUNLEVEL_HIGHEST')]
      
      [String] $Runlevel = 'TASK_RUNLEVEL_LUA',
      [ValidateSet('Network Service','Local System')]
      [String] $TaskAccount = 'Local System',
      [String] $DisableTime = $null
    
    )
    
    $rlevels=@{'TASK_RUNLEVEL_LUA'=0;'TASK_RUNLEVEL_HIGHEST'=1}
    $raccounts=@{'Network Service'="S-1-5-20";'Local System'="S-1-5-18"}
    [string] $Arguments = '-NoProfile -WindowStyle Hidden -file ' + $PowerShellScriptPath + ' -eventChannel $(eventChannel) -eventData $(eventData) -eventSeverity $(eventSeverity) -eventRecordID $(eventRecordID)'
    
    #Is Admin?
    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    if($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){


      $Service = $null

      $Service = new-object -ComObject ("Schedule.Service")
      $Service.Connect()
      $RootFolder = $Service.GetFolder("\")
      $TaskDefinition = $Service.NewTask(0) # TaskDefinition object https://msdn.microsoft.com/en-us/library/windows/desktop/aa382542(v=vs.85).aspx
      $TaskDefinition.RegistrationInfo.Description = ''
      $TaskDefinition.RegistrationInfo.Author='andi'
    
      $TaskDefinition.Settings.Enabled = $True
      $TaskDefinition.Settings.AllowDemandStart = $True
      $TaskDefinition.Settings.DisallowStartIfOnBatteries = $False
      $Triggers = $TaskDefinition.Triggers
      $Trigger = $Triggers.Create(0) ## 0 is an event trigger https://msdn.microsoft.com/en-us/library/windows/desktop/aa383898(v=vs.85).aspx
      $Trigger.Enabled = $true
      
      $Trigger.EndBoundary = $DisableTime
      $Trigger.Id = $EventID 
 
      $Trigger.Subscription = $("<QueryList><Query Id='0' Path='"+$Logname+"'><Select Path='"+$Logname+"'>*[System[(EventID="+ $EventID +")]]</Select></Query></QueryList>")

      # This is new! It is possible to pipe the eventdatea to the script

      $Trigger.ValueQueries.Create('eventChannel','Event/System/Channel') | Out-Null
      $Trigger.ValueQueries.Create('eventRecordID','Event/System/EventRecordID') | Out-Null
      $Trigger.ValueQueries.Create('eventSeverity','Event/System/Level') | Out-Null
      $Trigger.ValueQueries.Create('eventData','Event/EventData/Data') | Out-Null

      $Principal = $taskDefinition.Principal
      $Principal.LogonType = 5 # TASK_LOGON_SERVICE_ACCOUNT Indicates that a Local System, Local Service, or Network Service account is being used as a security context to run the task.
                             # https://docs.microsoft.com/en-us/windows/desktop/taskschd/principal-logontype
      
      $Principal.RunLevel = $rlevels[$Runlevel]  
      $taskDefinition.Principal=$Principal

      $Action = $TaskDefinition.Actions.Create(0)
      $Action.Path = $PowerShellExePath
      $action.Arguments = $Arguments
      $RootFolder.RegisterTaskDefinition($taskName, $TaskDefinition, 6, "S-1-5-20", $null, 5) | Out-Null
    }
    else {
      Write-Warning 'You need Admin rights to install - Try running the command again in a session that has been opened with elevated user rights (that is, Run as Administrator)'

    }
  }

 For example, a new task can be created as follows

New-ScheduledEventtriggerTask -TaskName MyTask -PowerShellScriptPath 'c:\temp\testEvent.ps1' -Logname MyEventLog -EventID 100 -Runlevel TASK_RUNLEVEL_LUA -TaskAccount 'Local System'

 Finally here is an example script for the planned task. In the header you can see the parameters, which are passed with

<#
.Synopsis
   Simple task for New-ScheduledEventtriggerTask 
.DESCRIPTION
   
#>

Param(
  [String] $eventChannel, 
  [int] $eventRecordID, 
  [String] $eventData,
  [String] $eventSeverity
)
    
$OutFile = "C:\temp\text.txt"

"Running Action" | Out-File -FilePath $OutFile -Append
"eventChannel $eventChannel" | Out-File -FilePath $OutFile -Append
"eventRecordID $eventRecordID" | Out-File -FilePath $OutFile -Append
"eventData $eventData" | Out-File -FilePath $OutFile -Append
"eventSeverity $eventSeverity" | Out-File -FilePath $OutFile -Append

#Write-EventLog -LogName 'MyEventlog' -Source 'powershell.exe' -EventId 100 -Message "<Publish>Testdata</Publish>"
$myXml = [xml] $eventData
switch ($myXml.Publish)
{
  "TestData"   { 
                 "Publish Testdata" | Out-File -FilePath $OutFile -Append
               }
  "myData"     { "Publish MyData" | Out-File -FilePath $OutFile -Append}

  default      { 'anything else'  | Out-File -FilePath $OutFile -Append}
}