Skip to content

Instantly share code, notes, and snippets.

@jdhitsolutions
Last active February 17, 2024 23:33
Show Gist options
  • Save jdhitsolutions/1b9dfb31fef91f34c54b344c6516c30b to your computer and use it in GitHub Desktop.
Save jdhitsolutions/1b9dfb31fef91f34c54b344c6516c30b to your computer and use it in GitHub Desktop.
This PowerShell function uses WMI via the Get-CimInstance command to query the state of installed anti-virus products.
#requires -version 5.1
Function Get-AVStatus {
<#
.Synopsis
Get anti-virus product information.
.Description
This command uses WMI via the Get-CimInstance command to query the state of installed anti-virus products. The default behavior is to only display enabled products, unless you use -All. You can query by computername or existing CIMSessions.
.Example
PS C:\> Get-AVStatus chi-win10
Displayname : ESET NOD32 Antivirus 9.0.386.0
ProductState : 266256
Enabled : True
UpToDate : True
Path : C:\Program Files\ESET\ESET NOD32 Antivirus\ecmd.exe
Timestamp : Thu, 21 Jul 2016 15:20:18 GMT
Computername : CHI-WIN10
.Example
PS C:\> import-csv s:\computers.csv | Get-AVStatus -All | Group Displayname | Select Name,Count | Sort Count,Name
Name Count
---- -----
ESET NOD32 Antivirus 9.0.386.0 12
ESET Endpoint Security 5.0 6
Windows Defender 4
360 Total Security 1
Import a CSV file which includes a Computername heading. The imported objects are piped to this command. The results are sent to Group-Object.
.Example
PS C:\> $cs | Get-AVStatus | where {-Not $_.UptoDate}
Displayname : ESET NOD32 Antivirus 9.0.386.0
ProductState : 266256
Enabled : True
UpToDate : False
Path : C:\Program Files\ESET\ESET NOD32 Antivirus\ecmd.exe
Timestamp : Wed, 20 Jul 2016 11:10:13 GMT
Computername : CHI-WIN11
Displayname : ESET NOD32 Antivirus 9.0.386.0
ProductState : 266256
Enabled : True
UpToDate : False
Path : C:\Program Files\ESET\ESET NOD32 Antivirus\ecmd.exe
Timestamp : Thu, 07 Jul 2016 15:15:26 GMT
Computername : CHI-WIN81
You can also pipe CIMSession objects. In this example, the output are enabled products that are not up to date.
.Notes
version: 1.1
Learn more about PowerShell:
http://jdhitsolutions.com/blog/essential-powershell-resources/
.Inputs
[string[]]
[Microsoft.Management.Infrastructure.CimSession[]]
.Outputs
[pscustomboject]
.Link
Get-CimInstance
#>
[cmdletbinding(DefaultParameterSetName = "computer")]
Param(
#The name of a computer to query.
[Parameter(
Position = 0,
ValueFromPipeline,
ValueFromPipelineByPropertyName,
ParameterSetName = "computer"
)]
[ValidateNotNullorEmpty()]
[string[]]$Computername = $env:COMPUTERNAME,
#An existing CIMsession.
[Parameter(ValueFromPipeline, ParameterSetName = "session")]
[Microsoft.Management.Infrastructure.CimSession[]]$CimSession,
#The default is enabled products only.
[switch]$All
)
Begin {
Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"
Function ConvertTo-Hex {
Param([int]$Number)
'0x{0:x}' -f $Number
}
#initialize an hashtable of paramters to splat to Get-CimInstance
$cimParams = @{
Namespace = "root/SecurityCenter2"
ClassName = "Antivirusproduct"
ErrorAction = "Stop"
}
If ($All) {
Write-Verbose "[BEGIN ] Getting all AV products"
}
$results = @()
} #begin
Process {
#initialize an empty array to hold results
$AV = @()
Write-Verbose "[PROCESS] Using parameter set: $($pscmdlet.ParameterSetName)"
Write-Verbose "[PROCESS] PSBoundparameters: "
Write-Verbose ($PSBoundParameters | Out-String)
if ($pscmdlet.ParameterSetName -eq 'computer') {
foreach ($computer in $Computername) {
Write-Verbose "[PROCESS] Querying $($computer.ToUpper())"
$cimParams.ComputerName = $computer
Try {
$AV += Get-CimInstance @CimParams
}
Catch {
Write-Warning "[$($computer.ToUpper())] $($_.Exception.Message)"
$cimParams.ComputerName = $null
}
} #foreach computer
}
else {
foreach ($session in $CimSession) {
Write-Verbose "[PROCESS] Using session $($session.computername.toUpper())"
$cimParams.CimSession = $session
Try {
$AV += Get-CimInstance @CimParams
}
Catch {
Write-Warning "[$($session.computername.ToUpper())] $($_.Exception.Message)"
$cimParams.cimsession = $null
}
} #foreach computer
}
foreach ($item in $AV) {
Write-Verbose "[PROCESS] Found $($item.Displayname)"
$hx = ConvertTo-Hex $item.ProductState
$mid = $hx.Substring(3, 2)
if ($mid -match "00|01") {
$Enabled = $False
}
else {
$Enabled = $True
}
$end = $hx.Substring(5)
if ($end -eq "00") {
$UpToDate = $True
}
else {
$UpToDate = $False
}
$results += $item | Select-Object Displayname, ProductState,
@{Name = "Enabled"; Expression = { $Enabled } },
@{Name = "UpToDate"; Expression = { $UptoDate } },
@{Name = "Path"; Expression = { $_.pathToSignedProductExe } },
Timestamp,
@{Name = "Computername"; Expression = { $_.PSComputername.toUpper() } }
} #foreach
} #process
End {
If ($All) {
$results
}
else {
#filter for enabled only
($results).Where( { $_.enabled })
}
Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)"
} #end
} #end function
@jdhitsolutions
Copy link
Author

You don't pipe Get-CimInstance. Just run Get-AVStatus -all

@paschott
Copy link

paschott commented Aug 21, 2023

Doing that, I get:

The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".

I did manage to get WinRM enabled - got the results, but I think I still need to use the example you posted above for the virus definition dates and such.
Get-cimInstance -Namespace root/microsoft/protectionmanagement -class msft_mpcomputerstatus

We're trying to make sure things are enabled, but also reasonably up to date. I think this shows the app is up to date, but doesn't say anything about the definitions.

@jdhitsolutions
Copy link
Author

You definitely need PowerShell remoting enabled for this to work against a remote computer. My function is limited to what the CIM class can report. My function will tell you the state of the application. It isn't designed to tell you anything about signature files.

@paschott
Copy link

Hmm - that was against my local machine, which is why I thought it was odd to have to enable WinRM for it to work. It did work. I just need to run that additional script you provided for the signatures to make sure someone's not running with crazy old sigs. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment