-
-
Save jdhitsolutions/1b9dfb31fef91f34c54b344c6516c30b to your computer and use it in GitHub Desktop.
#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 |
There are limitations to this solution. What operating system and PowerShell version are you running? It is also possible that the vendor for your AV product isn't populating the CIM database.
There are limitations to this solution. What operating system and PowerShell version are you running? It is also possible that the vendor for your AV product isn't populating the CIM database.
Windows 11 Pro
PSVersion 5.1.22621.963
I can also get it to work querying a Windows 10 VM remotely.
I trust the code works. You could verify if the classes even exist.
If the classes exist, try querying the instances directly.
Get-Ciminstance -namespace root\securitycenter2 -ClassName antivirusproduct
If you get no result, either the vendor isn't populating the instance with information, or some policy might be preventing you from querying this information.
That's a legacy approach to what I am doing. The only other thing I can think of is that the WSMan ports are disabled, which would prevent the CIM cmdlets from querying remote computers. But it shouldn't have an effect if you run the command locally.
I can run this without issue - see Windows Defender and what seems to be the most recent definitions:
Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct
If I run the Get-AVStatus function as in the blog post, I get nothing. Running on Win11 Pro, using PS v5.1 ISE to load up the function/code.
Get-CimInstance | Get-AVStatus -all
## no results
You don't pipe Get-CimInstance. Just run Get-AVStatus -all
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.
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.
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. :)
Code does not return anything when ran.