PowerShell Windows Event Forwarding Setup via Script

Centralized Logging Without a SIEM
Commercial SIEM platforms solve centralized log collection, but they come with licensing costs, deployment complexity, and a steep learning curve. For environments where the primary goal is aggregating Windows Security, System, and Application logs from a defined set of servers into one queryable location, Windows Event Forwarding provides that capability natively — no agents, no third-party software, and no recurring fees. PowerShell can configure the entire stack: collector setup, source enrollment, subscription creation, and validation.
Quick Answer
Run winrm quickconfig on the collector, enable WinRM on sources via GPO or PowerShell, create an event subscription with wecutil cs, and validate with Get-WinEvent -LogName ForwardedEvents on the collector.
Configuring the Collector with winrm quickconfig and wecutil
The collector is the machine that receives forwarded events. It needs WinRM running and the Windows Event Collector service started. Run these commands elevated on the collector once.
# On the collector — run as administrator
winrm quickconfig -quiet
wecutil qc -quiet # Quick-configure the Windows Event Collector service
# Verify the WEC service is running
Get-Service -Name Wecsvc | Select-Object Name, Status, StartType
After wecutil qc, the NETWORK SERVICE account on the collector is granted access to create the ForwardedEvents log. The Wecsvc service is set to Automatic start. You can confirm both with Get-WinEvent -ListLog ForwardedEvents.
Enabling WinRM on Source Computers via GPO or PowerShell
Sources must have WinRM running and must trust the collector to pull events. For a handful of machines, a direct PowerShell remoting call is the fastest path. For domain-wide rollout, a Group Policy Object targeting Computer Configuration > Windows Settings > Security Settings > Windows Firewall and the WinRM service policy is preferable.
# Enable WinRM on a batch of source computers
$sources = 'SRV01', 'SRV02', 'SRV03'
Invoke-Command -ComputerName $sources -ScriptBlock {
winrm quickconfig -quiet
# Allow collector to read the Security log
$sddl = (Get-WinEvent -ListLog Security).SecurityDescriptor
Write-Output "Security log SDDL on $env:COMPUTERNAME`: $sddl"
} -ErrorAction Stop
The NETWORK SERVICE account on the collector needs Read permission on the Security event log of each source. Add the collector’s NETWORK SERVICE to the log’s security descriptor using wevtutil sl Security /ca:<updated-sddl> or via a GPO audit policy.
Creating an Event Subscription with wecutil cs
A subscription is an XML document that describes which events to forward, which sources to pull from, and how to deliver them. The wecutil cs command imports that XML on the collector. Below is a minimal Security log subscription targeting specific Event IDs.
# subscription.xml — save this file, then import with wecutil
$subscriptionXml = @'
<Subscription xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription">
<SubscriptionId>SecurityAudit</SubscriptionId>
<SubscriptionType>SourceInitiated</SubscriptionType>
<Description>Collect logon and privilege events</Description>
<Enabled>true</Enabled>
<Uri>http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog</Uri>
<ConfigurationMode>Normal</ConfigurationMode>
<Delivery Mode="Push">
<Batching><MaxItems>20</MaxItems><MaxLatencyTime>900000</MaxLatencyTime></Batching>
</Delivery>
<Query><![CDATA[<QueryList><Query Id="0">
<Select Path="Security">*[System[(EventID=4624 or EventID=4625 or EventID=4648)]]</Select>
</Query></QueryList>]]></Query>
<AllowedSourceDomainComputers>O:NSG:NSD:(A;;GA;;;DC)</AllowedSourceDomainComputers>
</Subscription>
'@
$xmlPath = "$env:TEMP\SecurityAudit.xml"
$subscriptionXml | Out-File -FilePath $xmlPath -Encoding UTF8
wecutil cs $xmlPath
Automating Subscription Creation with PowerShell Wrapper Functions
Wrapping wecutil in PowerShell makes subscription management repeatable and scriptable. The function below accepts parameters, generates the XML, imports it, and returns the subscription status — turning a multi-step manual process into a single function call.
function New-WefSubscription {
param(
[Parameter(Mandatory)][string]$SubscriptionId,
[Parameter(Mandatory)][string]$QueryXml,
[string]$Description = '',
[string]$AllowedSDDL = 'O:NSG:NSD:(A;;GA;;;DC)'
)
$xmlContent = @"
<Subscription xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription">
<SubscriptionId>$SubscriptionId</SubscriptionId>
<SubscriptionType>SourceInitiated</SubscriptionType>
<Description>$Description</Description>
<Enabled>true</Enabled>
<Uri>http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog</Uri>
<ConfigurationMode>Normal</ConfigurationMode>
<Query><![CDATA[$QueryXml]]></Query>
<AllowedSourceDomainComputers>$AllowedSDDL</AllowedSourceDomainComputers>
</Subscription>
"@
$tmp = [System.IO.Path]::GetTempFileName() + '.xml'
$xmlContent | Out-File -FilePath $tmp -Encoding UTF8
wecutil cs $tmp
wecutil gs $SubscriptionId # print status
Remove-Item $tmp
}
New-WefSubscription -SubscriptionId 'SecurityAudit' `
-QueryXml '<QueryList><Query Id="0"><Select Path="Security">*[System[EventID=4624]]</Select></Query></QueryList>' `
-Description 'Logon events from domain computers'
Validating Forwarded Events with Get-WinEvent on Collector
After 10–15 minutes (depending on delivery latency settings), events should appear in the ForwardedEvents log on the collector. Use Get-WinEvent to confirm events are arriving and identify which source computers are contributing.
Get-WinEvent -LogName ForwardedEvents -MaxEvents 50 |
Select-Object TimeCreated,
@{N='Source';E={$_.Properties[0].Value}},
Id, Message |
Sort-Object TimeCreated -Descending |
Format-Table -AutoSize
Troubleshooting: Event 100 and Source Connection Failures
The most common failure mode is Event ID 100 in the Microsoft-Windows-EventCollector/Operational log on the collector. This event means a source tried to connect but was rejected. Check these areas in order: Kerberos SPN registration on the collector (setspn -L <collector>), NETWORK SERVICE read permission on the source’s Security log, and WinRM listener status on the source (winrm enumerate winrm/config/listener).
Common Errors
- NETWORK SERVICE account needs Read permission on the Security log on source computers. Without this, the source cannot grant the collector access to pull Security events. Add the collector computer account or NETWORK SERVICE to the log DACL via
wevtutil sl Securityon each source, or deploy the permission via Group Policy. - Subscription shows Active but events do not flow — Kerberos SPN must be set on collector. For source-initiated subscriptions, sources use Kerberos to authenticate to the collector’s WinRM endpoint. If the HTTP SPN is missing on the collector’s computer account, authentication silently fails. Register it with
setspn -A HTTP/<collector-fqdn> <collector-netbios>.
Related Cmdlets / See Also
Wrapping Up
Windows Event Forwarding configured entirely through PowerShell gives you centralized log collection with zero per-server agent overhead. The key steps — collector setup with wecutil qc, subscription import, and NETWORK SERVICE permission on source Security logs — are all scriptable and repeatable, making WEF a practical choice for security monitoring on any domain-joined fleet.


