Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Archives
Log in
Subscribe
September 25, 2026

Solving The Antimalware Status Challenge

In this issue:

  • A Starting Point
  • Diving into Qualifiers
  • Get-AntimalwareHealthStatus
  • Summary

Let's re-visit the scripting challenge I gave you at the end of last month. I challenged you to create a PowerShell tool that would provide information from the AntimalwareHealthStatus WMI class found in the root\Microsoft\SecurityClient namespace. Naturally, I wanted your code to query a remote computer and at a minimum show this information:

  • The computer name
  • The enabled status
  • The product status
  • The spyware signature version
  • the antivirus signature version
  • the time of the last quick scan
  • the time of the last full scan

For bonus points, I asked you to decode the ProductStatus and scanning sources from integers (technically a byte) to descriptions, i.e. System.

I hope you at least started tackling this problem. There are some good scripting techniques that I know you can apply to other projects.

A Starting Point

I told you where to start so it makes sense to see what you have to work with:

PS C:\> Get-CimInstance -Namespace root\Microsoft\SecurityClient -ClassName AntimalwareHealthStatus

PackedXml                          : <instance classname="AntimalwareHealthStatu
                                     s"><property name="AntispywareEnabled" type="boolean"><value>TRUE</value></property><p name="AntispywareSignatureAge" roperty="" type="uint32"><value>0</value><prope ...="" rty="">
SchemaVersion                      : 1.0.0.1
Enabled                            : True
Name                               : Antimalware
Version                            : 4.18.26090.7
AntispywareEnabled                 : True
AntispywareSignatureAge            : 0
AntispywareSignatureUpdateDateTime : 2026-09-25T09:30:43.000Z
AntispywareSignatureVersion        : 1.459.398.0
AntivirusEnabled                   : True
AntivirusSignatureAge              : 0
AntivirusSignatureUpdateDateTime   : 2026-09-25T09:30:42.000Z
AntivirusSignatureVersion          : 1.459.398.0
BehaviorMonitorEnabled             : True
EngineVersion                      : 1.1.26090.9
IoavProtectionEnabled              : True
LastFullScanAge                    : 4294967295
LastFullScanDateTimeEnd            :
LastFullScanDateTimeStart          :
LastFullScanSource                 : 0
LastQuickScanAge                   : 6
LastQuickScanDateTimeEnd           : 2026-09-19T00:54:57.769Z
LastQuickScanDateTimeStart         : 2026-09-19T00:51:35.070Z
LastQuickScanSource                : 2
NisEnabled                         : True
NisEngineVersion                   : 1.1.26090.9
NisSignatureVersion                : 1.459.398.0
OnAccessProtectionEnabled          : True
ProductStatus                      : 524288
RealTimeScanDirection              : 0
RtpEnabled                         : True
PSComputerName                     :

This looks rather straightforward. Although, you might want to look at the class definition. Instead of using Get-CimClass, let's use Get-CimClassProperty from the PSScriptTools module.

PS C:\&gt; Get-CimClassProperty -Namespace root\Microsoft\SecurityClient -ClassName AntimalwareHealthStatus

   Class: root/Microsoft/SecurityClient:AntimalwareHealthStatus

Property                           ValueType Flags
--------                           --------- -----
AntispywareEnabled                 Boolean   ReadOnly
AntispywareSignatureAge            UInt32    ReadOnly
AntispywareSignatureUpdateDateTime String    ReadOnly
AntispywareSignatureVersion        String    ReadOnly
AntivirusEnabled                   Boolean   ReadOnly
AntivirusSignatureAge              UInt32    ReadOnly
AntivirusSignatureUpdateDateTime   String    ReadOnly
AntivirusSignatureVersion          String    ReadOnly
BehaviorMonitorEnabled             Boolean   ReadOnly
Enabled                            Boolean   ReadOnly
EngineVersion                      String    ReadOnly
IoavProtectionEnabled              Boolean   ReadOnly
LastFullScanAge                    UInt32    ReadOnly
LastFullScanDateTimeEnd            String    ReadOnly
LastFullScanDateTimeStart          String    ReadOnly
LastFullScanSource                 UInt8     ReadOnly
LastQuickScanAge                   UInt32    ReadOnly
LastQuickScanDateTimeEnd           String    ReadOnly
LastQuickScanDateTimeStart         String    ReadOnly
LastQuickScanSource                UInt8     ReadOnly
Name                               String    ReadOnly
NisEnabled                         Boolean   ReadOnly
NisEngineVersion                   String    ReadOnly
NisSignatureVersion                String    ReadOnly
OnAccessProtectionEnabled          Boolean   ReadOnly
PackedXml                          String    ReadOnly
ProductStatus                      UInt32    ReadOnly
RealTimeScanDirection              UInt8     ReadOnly
RtpEnabled                         Boolean   ReadOnly
SchemaVersion                      String    ReadOnly
Version                            String    ReadOnly

This is useful because this tells us that the datetime properties are technically strings so we'll need to convert them.

I know I'll only need a subset of these properties:

PS C:\&gt; Get-CimInstance -Namespace root\Microsoft\SecurityClient -ClassName AntimalwareHealthStatus | Select-Object ProductStatus,*end,*source,*version,*enabled | Tee-Object -variable t

ProductStatus               : 524288
LastFullScanDateTimeEnd     :
LastQuickScanDateTimeEnd    : 2026-09-19T00:54:57.769Z
LastFullScanSource          : 0
LastQuickScanSource         : 2
SchemaVersion               : 1.0.0.1
Version                     : 4.18.26090.7
AntispywareSignatureVersion : 1.459.398.0
AntivirusSignatureVersion   : 1.459.398.0
EngineVersion               : 1.1.26090.9
NisEngineVersion            : 1.1.26090.9
NisSignatureVersion         : 1.459.398.0
Enabled                     : True
AntispywareEnabled          : True
AntivirusEnabled            : True
BehaviorMonitorEnabled      : True
IoavProtectionEnabled       : True
NisEnabled                  : True
OnAccessProtectionEnabled   : True
RtpEnabled                  : True

This is more than I will eventually need, but it gives me something to work with. For example, I can figure out how I'm going to handle datetime values.

PS C:\&gt; $t.LastQuickScanDateTimeEnd
2026-09-19T00:54:57.769Z
PS C:\&gt; $t.LastQuickScanDateTimeEnd -as [datetime]

Friday, September 18, 2026 8:54:57 PM

That's pretty easy.

Want to read the full issue?
Already a paid subscriber? Click here to log in.
GitHub
Bluesky
LinkedIn
Mastodon
jdhitsolutions.github.io
Powered by Buttondown, the easiest way to start and grow your newsletter.