Skip to main content

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.
No Native CMD Tool

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.

SEO and UX Tip

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

  1. Check the Event Viewer: Defender also logs threats to the Windows Event Viewer: Applications and Services Logs > Microsoft > Windows > Windows Defender > Operational. Use wevtutil to query this log from Batch.
  2. Verify Quarantined Files: Use Get-MpThreat to find where the malware was located before it was moved to quarantine.
  3. 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.
Third-Party AVs

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.