How to Monitor and Log EXE Program Execution with Command Line Arguments in Windows


2 views

Windows doesn't natively maintain a comprehensive log of all EXE executions by default, but several approaches can help track this information:

# PowerShell command to query recent process creations
Get-WinEvent -FilterHashtable @{
    LogName='Security'
    ID='4688'
} -MaxEvents 20 | Format-List

You need to enable audit policies first:

  1. Run 'gpedit.msc' (Local Group Policy Editor)
  2. Navigate to: Computer Configuration → Windows Settings → Security Settings → Advanced Audit Policy Configuration → System Audit Policies → Detailed Tracking
  3. Enable "Audit Process Creation"

Sysinternals Process Monitor (ProcMon) is the most powerful tool for this purpose:

# Example filter to capture EXE launches with arguments
procmon.exe /BackingFile log.pml /Quiet /Filter "Operation is Process Start"

For continuous logging, configure ETW (Event Tracing for Windows):

# Create a session that logs process creations
logman create trace ProcessLogger -p Microsoft-Windows-Kernel-Process 0x10 -o proc.etl
logman start ProcessLogger

# To stop and convert to readable format
logman stop ProcessLogger
tracerpt proc.etl -o proc.csv -of CSV

This PowerShell script extracts process creation events with arguments:


$events = Get-WinEvent -FilterHashtable @{
    LogName='Security'
    ID=4688
} -MaxEvents 500

$events | ForEach-Object {
    $eventXml = ([xml]$_.ToXml()).Event
    $commandLine = ($eventXml.EventData.Data | Where-Object {$_.Name -eq 'CommandLine'}).'#text'
    $parentProcess = ($eventXml.EventData.Data | Where-Object {$_.Name -eq 'ParentProcessName'}).'#text'
    
    [PSCustomObject]@{
        TimeCreated = $_.TimeCreated
        ProcessName = $_.Properties[5].Value
        CommandLine = $commandLine
        ParentProcess = $parentProcess
        User = $_.Properties[1].Value
    }
} | Export-Csv -Path "ProcessLogs.csv" -NoTypeInformation

For enterprise environments consider:

  • Splunk Universal Forwarder with Windows TA
  • Elastic Winlogbeat
  • Graylog Sidecar

These solutions provide centralized collection and analysis of process execution events across multiple systems.


Windows doesn't natively log all EXE executions by default, but you can enable process creation auditing:

1. Open Group Policy Editor (gpedit.msc)
2. Navigate to: 
   Computer Configuration → Windows Settings → 
   Security Settings → Advanced Audit Policy → 
   Audit Policies → Detailed Tracking
3. Enable "Audit Process Creation"
4. Run: gpupdate /force

After enabling this, check Event Viewer under:
Windows Logs → Security (Event ID 4688). While this shows process creation, command line arguments aren't logged by default in all Windows versions.

For more detailed logging including arguments, use this PowerShell script that leverages ETW (Event Tracing for Windows):

# Requires admin privileges
$Query = @"
<QueryList>
  <Query Id="0" Path="Microsoft-Windows-Kernel-Process/Analytic">
    <Select Path="Microsoft-Windows-Kernel-Process/Analytic">
      *[System[Provider[@Name='Microsoft-Windows-Kernel-Process'] 
      and (EventID=1 or EventID=5 or EventID=10)]] 
    </Select>
  </Query>
</QueryList>
"@

$Action = {
    $Event = $EventArgs.EventRecord
    $Time = $Event.TimeCreated
    $PID = $Event.Properties[3].Value
    $ImageName = $Event.Properties[4].Value
    $CommandLine = $Event.Properties[8].Value
    
    Write-Host "[$Time] $ImageName (PID: $PID)"
    Write-Host "CommandLine: $CommandLinen"
}

Register-WinEvent -Query $Query -Action $Action -MaxEvents 1000

For immediate debugging needs, Sysinternals ProcMon is the gold standard:

  1. Download from Microsoft's site
  2. Set filter: Operation is "Process Create"
  3. Columns to enable: Process Name, PID, Command Line, Date/Time
  4. Optionally log to file (File → Save...)

For persistent logging, create a WMI event consumer:

$Query = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"
$Action = {
    $Process = $EventArgs.NewEvent.TargetInstance
    $LogEntry = @{
        Time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        Name = $Process.Name
        PID = $Process.ProcessId
        CommandLine = $Process.CommandLine
        ParentPID = $Process.ParentProcessId
    }
    $LogEntry | Export-Csv -Path "C:\ProcessLog.csv" -Append -NoTypeInformation
}

Register-WmiEvent -Query $Query -Action $Action -SourceIdentifier "ProcessTracker"

For kernel-level tracing with maximum detail:

logman create trace ProcessLogger -p Microsoft-Windows-Kernel-Process -o proc.etl
logman start ProcessLogger
# Capture data...
logman stop ProcessLogger
# Convert to readable format:
tracerpt proc.etl -o proc.csv -of CSV