How to Check Windows Defender Threat History in Batch Script
Monitoring threat history is a vital part of maintaining a secure Windows environment. While the "Windows Security" app provides a visual summary of recent blocks and quarantines, system administrators often need to pull this data programmatically to audit machine health or investigate a security incident across multiple workstations. By using PowerShell within a Batch script, you can retrieve a detailed log of every threat Windows Defender has detected, along with its severity and current status. This guide explains how to extract your security history effectively.
Why Audit Threat History via Script?
- Incident Forensics: Identifying the exact name and path of a blocked file to determine its origin.
- Compliance Monitoring: Ensuring that a fleet of computers is remaining "Clean" and that threats are being handled automatically.
- Proactive Alerts: Including a threat check as part of a daily "System Health" Batch report.
The standard MpCmdRun.exe tool does not provide a command to "List History" for security reasons. However, the information is stored in the Windows Event Logs and the Defender-specific WMI objects, which we can access via PowerShell.
Method 1: Using Get-MpThreat (The Professional Way)
The Get-MpThreat cmdlet provides a comprehensive list of all active and historical threats detected by the Microsoft Defender engine.
@echo off
setlocal
:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required to view threat history.
pause
exit /b 1
)
echo [PROCESS] Retrieving recent threat history...
echo.
:: We call PowerShell and format the output as a table
powershell -NoProfile -Command ^
"$threats = Get-MpThreat;" ^
"if ($threats) {" ^
" $threats | Select-Object ThreatName, SeverityID, InitialDetectionTime, Resources | Format-Table -AutoSize" ^
"} else {" ^
" Write-Host '[INFO] No threats found. System appears clean.'" ^
"}"
pause
Method 2: Detecting Active Threats Only
If you only want to see threats that have not yet been resolved (not yet cleaned or quarantined), you can filter the results.
@echo off
setlocal
:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)
echo [PROCESS] Searching for ACTIVE (unresolved^) threats...
echo.
powershell -NoProfile -Command ^
"$active = Get-MpThreat | Where-Object { $_.IsActive -eq $true };" ^
"if ($active) {" ^
" Write-Host '[WARNING] Active threats detected:' -ForegroundColor Red;" ^
" $active | Select-Object ThreatName, SeverityID, Resources | Format-Table -AutoSize" ^
"} else {" ^
" Write-Host '[SUCCESS] No active threats found.'" ^
"}"
pause
Creating a Security Inspection Report
This script generates a timestamped text file containing all detected threats, which is perfect for administrative record-keeping.
@echo off
setlocal
:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)
set "REPORT=%~dp0Security_Threat_Log_%COMPUTERNAME%_%date:~-4%%date:~-10,2%%date:~-7,2%.txt"
echo [PROCESS] Generating threat report for %COMPUTERNAME%...
:: Generate the full report via a single PowerShell call
powershell -NoProfile -Command ^
"'--- SECURITY AUDIT: THREAT HISTORY ---';" ^
"'Computer: ' + $env:COMPUTERNAME;" ^
"'Generated: ' + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss');" ^
"'';" ^
"$threats = Get-MpThreat;" ^
"if ($threats) {" ^
" 'Total threats found: ' + $threats.Count;" ^
" '';" ^
" $threats | Select-Object ThreatName, SeverityID, InitialDetectionTime, @{Name='Path';Expression={$_.Resources}} | Format-List" ^
"} else {" ^
" 'No threats detected. System is clean.'" ^
"}" ^
> "%REPORT%" 2>nul
if %errorlevel% equ 0 (
echo [SUCCESS] Report saved to: %REPORT%
echo [ACTION] Please review this file for any security concerns.
) else (
echo [ERROR] Failed to generate report. Code: %errorlevel%
)
pause
Common Pitfalls and How to Avoid Them
Administrative Rights
Accessing security logs and the threat database requires Administrator privileges.
Wrong Way:
:: Running as a standard user
powershell -Command "Get-MpThreat"
:: Result: Access Denied or empty result.
Empty Results
If the command returns nothing, it is usually a Good Sign. It means that Windows Defender has not detected any threats on the machine during the logged period.
Advise your users that if the list is empty, their system is "Clean." However, they should also run powershell -NoProfile -Command "Get-MpPreference" to ensure that detection isn't being suppressed or that real-time protection isn't disabled.
Best Practices for Threat Monitoring
- Check the Event Viewer: Defender also logs threats to the Windows Event Viewer:
Applications and Services Logs > Microsoft > Windows > Windows Defender > Operational. Usewevtutilto query this log from Batch. - Verify Quarantined Files: Use
Get-MpThreatto find where the malware was located before it was moved to quarantine. - Cross-Check with Logs: Combine your threat history audit with a check on when the last full scan was performed to ensure the history is up-to-date.
If a third-party antivirus is installed, Windows Defender is typically disabled, and Get-MpThreat will return an error or produce no data. This is normal behavior.
Conclusion
Checking the Windows Defender threat history via Batch script is a critical competency for any security-conscious administrator. By leveraging PowerShell to reveal the history of detections, paths, and severity levels, you can maintain a clear and automated view of your system's security health. This professional approach to system auditing ensures that no incident goes unnoticed, simplifies forensic investigations, and provides a robust, well-documented trail of defense for your entire Windows infrastructure.