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.
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} }
Comments