Query Details

Windows Trigger Full Scan For Devices That Have Not Completed One Windows Clients Only

Query

// Initial full scan helper for MDE onboarded devices
// Use this in a custom detection rule with the "Run antivirus scan" (Full scan) action.
let AvModeDescription = dynamic({"0":"Normal", "1":"Passive", "4":"EDR Block"});
let TimeRange = ago(1d);
// Build a set of Windows 10/11 client devices (no servers)
let WinClientDevices =
    DeviceInfo
    | where Timestamp > TimeRange
    | where OSPlatform in ("Windows10", "Windows11")
    | summarize arg_max(Timestamp, DeviceName) by DeviceId
    | project DeviceId;
// 1. Find devices in Normal AV mode that have NOT completed a full scan
let ScanCandidates =
    DeviceTvmInfoGathering
    | where Timestamp > TimeRange
    | join kind=inner (WinClientDevices) on DeviceId
    | extend AdditionalFields = parse_json(AdditionalFields)
    | extend AvMode = tostring(AvModeDescription[tostring(AdditionalFields.["AvMode"])])
    | extend FullScanStatus = coalesce(
        extractjson("$.Full.ScanStatus", tostring(AdditionalFields.AvScanResults)),
        "Not available"
      )
    | where isnotempty(AvMode) and AvMode has "Normal"
    | where FullScanStatus !has "Completed"
    // one latest TVM record per device
    | summarize arg_max(Timestamp, FullScanStatus, DeviceName) by DeviceId
    | project DeviceId, DeviceName, FullScanStatus;
// 2. Anchor on DeviceEvents to get a valid event (ReportId + Timestamp)
DeviceEvents
| where Timestamp > TimeRange
| join kind=inner (WinClientDevices) on DeviceId
| summarize arg_max(Timestamp, ReportId) by DeviceId
// 3. Join event anchor to the TVM scan status
| join kind=inner ScanCandidates on DeviceId
// 4. Final output for custom detection + device action
| project
    DeviceName,
    DeviceId,
    FullScanStatus,
    ReportId,   // REQUIRED for custom detections
    Timestamp   // REQUIRED for custom detections
    | take 50

Explanation

This query is designed to identify Windows 10 and Windows 11 client devices that are onboarded to Microsoft Defender for Endpoint (MDE) and have not completed a full antivirus scan. Here's a simplified breakdown of the query:

  1. Define Variables and Time Range:

    • AvModeDescription maps numeric antivirus modes to descriptive names.
    • TimeRange is set to the last 24 hours.
  2. Identify Windows Client Devices:

    • It filters for devices running Windows 10 or 11, ignoring servers.
    • It selects the most recent record for each device based on the timestamp.
  3. Find Scan Candidates:

    • It identifies devices in "Normal" antivirus mode that haven't completed a full scan.
    • It uses the DeviceTvmInfoGathering table to check the antivirus mode and scan status.
    • It selects the latest record for each device.
  4. Anchor on Device Events:

    • It uses the DeviceEvents table to find a valid event for each device, which includes a ReportId and Timestamp.
  5. Join Data and Output Results:

    • It combines the scan candidates with the device events to ensure each device has a valid event.
    • It outputs a list of up to 50 devices, including their name, ID, scan status, report ID, and timestamp, which are necessary for creating custom detection rules and triggering a full antivirus scan.

This query is useful for creating a custom detection rule that can trigger a full antivirus scan on devices that need it.

Details

Nathan Hutchinson profile picture

Nathan Hutchinson

Released: February 2, 2026

Tables

DeviceInfoDeviceTvmInfoGatheringDeviceEvents

Keywords

Devices

Operators

letdynamicagoinsummarizearg_maxbyprojectwherejoinkindonextendparse_jsontostringcoalesceextractjsonisnotemptyhas!hastake

Actions