Forum Discussion

eladfe's avatar
eladfe
Copper Contributor
Mar 23, 2025

KQL query for AV scan

Hay

I want to get info about the last time that AV scanned the computers in my org.

I write a this query : 

DeviceEvents

| where ActionType == "AntivirusScanCompleted"

| extend SCAN = parse_json(AdditionalFields). ScanTypeIndex

| summarize hint.strategy=shuffle arg_max( DeviceName, *) by DeviceName

 

but it doesnt give me the date and time when the acan has been preformrd.
Another question: one of the result of this scan is the parameter ScanID. for example: 

ScanId

{041A5DF1-3A85-49D5-B0B0-2231AF4AC13C}
What this string means ? 

Thank you.
Elad.

 

5 Replies

  • Hi Elad,

    to see all the scans for the last 7 days, you need to:

    Remove arg_max (which only takes the last event).

    Filter on TimeGenerated > ago(7d)

    For example:

    DeviceEvents
    | where ActionType == "AntivirusScanCompleted"
    | extend ScanType = parse_json(AdditionalFields).ScanTypeIndex
    | where TimeGenerated > ago(7d)
    | project DeviceName, ScanTime = TimeGenerated, ScanType, ScanId
    | order by DeviceName asc, ScanTime desc


    This will return to you, for each computer, all scan entries completed in the last 7 days (quick, full, etc.), sorted by most recent.

     

  • Hi Elad,

    To include the date and time when each scan ran, you need to use the "TimeGenerated" (or "Timestamp") column in your DeviceEvents table, it records exactly when the event was logged.

    For example:

    kql

    DeviceEvents
    | where ActionType == "AntivirusScanCompleted"
    | extend ScanType = parse_json(AdditionalFields).ScanTypeIndex
    | summarize arg_max(TimeGenerated, *) by DeviceName
    | project DeviceName, LastScanTime = TimeGenerated, ScanType, ScanId


    -Using arg_max(TimeGenerated, *) returns, for each DeviceName, the record with the newest timestamp, including all columns (so you get ScanId, etc.).
    -If you only need the timestamp of the last scan, you can simplify to:

    kql
    DeviceEvents
    | where ActionType == "AntivirusScanCompleted"
    | summarize LastScanTime = max(TimeGenerated) by DeviceName

    This produces a two‑column table: DeviceName | LastScanTime

    ScanId
    That value—`{041A5DF1-3A85-49D5-B0B0-2231AF4AC13C}`—is simply a **GUID** (Global Unique Identifier). Every scan run gets its own unique ID so you can reliably distinguish one scan event from another in your logs. It doesn’t encode any extra information (like scan type or date); it’s just a unique marker for that single scan.

    Hope this helps

    • eladfe's avatar
      eladfe
      Copper Contributor

      Thank you!

      how can i get results of all scans in the last 7 days for example ? 

      lets say a quick scan run yesterday and a full scan run 3 days ago. with this query it will show me the
       last scan = the quick scan that run yesterday but not the full scan tun 3 days ago.

    • eladfe's avatar
      eladfe
      Copper Contributor

      Thank you!

      how can i get results of all scans in the last 7 days for example ? 

      lets say a quick scan run yesterday and a full scan run 3 days ago. with this query it will show me the
       last scan = the quick scan that run yesterday but not the full scan tun 3 days ago.

      • I try to run your initial query and notice you are already extended new column as SCAN.
        So, if you would like only Full scan, have you tried to filter SCAN == "Full" or other value with the same meaning (maybe | where not (SCAN == "Quick")) My test tenant has only Quick scan so I cannot test this for you tho.

Resources