[GH-ISSUE #268] Win_Antivirus_Verify.ps1 may falsly detect AV as disabled or not up to date if multipe instances of the same AV are installed. #319

Open
opened 2026-03-14 01:15:06 +03:00 by kerem · 2 comments
Owner

Originally created by @SpookOz on GitHub (Feb 28, 2025).
Original GitHub issue: https://github.com/amidaware/community-scripts/issues/268

I've found that often when an AV updates itself, it leaves the old instance in the the security center. So often there are 2 instances with the same name displayName, pathToSignedProductExe and pathToSignedReportingExe but different instanceGuid. In these cases, this script seems to occassionally report one instance as being active, but the other as having updated defs. Therefor, it gives an error saying "There do not seem to be any active and / or up-to-date Antivirus! Please check the installed AV for issues."

May I propose an alternative script that combines instances with the same displayName and pulls the status from both?

# Ensure OS Build supports SecurityCenter2
if ([environment]::OSVersion.Version.Build -le 14393) {
    Write-Host "Antivirus check not supported on this OS. Exiting."
    exit 2
}

# Define Product State Flags
[Flags()] enum ProductState {
    Off = 0x0000
    On = 0x1000
    Snoozed = 0x2000
    Expired = 0x3000
}

[Flags()] enum SignatureStatus {
    UpToDate = 0x00
    OutOfDate = 0x10
}

[Flags()] enum ProductFlags {
    SignatureStatus = 0x000000F0
    ProductState = 0x0000F000
}

# Fetch installed AV products
$antivirusProducts = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct

if (-not $antivirusProducts) {
    Write-Host "No antivirus detected in SecurityCenter2! Please verify manually."
    exit 1
}

# Group AVs by displayName
$groupedAVs = $antivirusProducts | Group-Object -Property displayName

# Initialize AV status check
$avFound = $false
$avResults = @()

foreach ($group in $groupedAVs) {
    $avName = $group.Name
    $instances = $group.Group

    # Initialize merged status
    $isEnabled = $false
    $isUpToDate = $false

    $avOutput = "`n$avName"

    foreach ($av in $instances) {
        $productState = $av.productState

        # Extract "Status" (Enabled/Disabled) using bitwise AND
        $currentState = [ProductState]($productState -band [ProductFlags]::ProductState)
        $currentStatus = if ($currentState -eq [ProductState]::On) { "Enabled" } else { "Disabled" }

        # Extract "Definition Status" using bitwise AND
        $currentSignatureStatus = [SignatureStatus]($productState -band [ProductFlags]::SignatureStatus)
        $currentDefinitionStatus = if ($currentSignatureStatus -eq [SignatureStatus]::UpToDate) { "UpToDate" } else { "OutOfDate" }

        # Merge instances: AV is considered "Enabled" if any instance is enabled
        if ($currentStatus -eq "Enabled") {
            $isEnabled = $true
        }

        # Merge instances: AV is considered "UpToDate" if any instance is up to date
        if ($currentDefinitionStatus -eq "UpToDate") {
            $isUpToDate = $true
        }
    }

    # Final decision for this AV
    $finalStatus = if ($isEnabled) { "Enabled" } else { "Disabled" }
    $finalDefinitionStatus = if ($isUpToDate) { "UpToDate" } else { "OutOfDate" }

    $avOutput += "`n  - Status: $finalStatus"
    $avOutput += "`n  - Definitions: $finalDefinitionStatus"

    # Check if AV is enabled and up-to-date
    if ($finalStatus -eq "Enabled" -and $finalDefinitionStatus -eq "UpToDate") {
        $avFound = $true
    }

    # Store the AV results to display later
    $avResults += $avOutput
}

# Print summary message first
if ($avFound) {
    Write-Host "At least one antivirus is enabled and up-to-date."
} else {
    Write-Host "No active and up-to-date antivirus detected! Please check your AV software."
}

# Print the detailed AV results
$avResults | ForEach-Object { Write-Host $_ }

# Exit with appropriate status code
if (-not $avFound) {
    exit 1
}

exit 0  # Success
Originally created by @SpookOz on GitHub (Feb 28, 2025). Original GitHub issue: https://github.com/amidaware/community-scripts/issues/268 I've found that often when an AV updates itself, it leaves the old instance in the the security center. So often there are 2 instances with the same name displayName, pathToSignedProductExe and pathToSignedReportingExe but different instanceGuid. In these cases, this script seems to occassionally report one instance as being active, but the other as having updated defs. Therefor, it gives an error saying "There do not seem to be any active and / or up-to-date Antivirus! Please check the installed AV for issues." May I propose an alternative script that combines instances with the same displayName and pulls the status from both? ``` # Ensure OS Build supports SecurityCenter2 if ([environment]::OSVersion.Version.Build -le 14393) { Write-Host "Antivirus check not supported on this OS. Exiting." exit 2 } # Define Product State Flags [Flags()] enum ProductState { Off = 0x0000 On = 0x1000 Snoozed = 0x2000 Expired = 0x3000 } [Flags()] enum SignatureStatus { UpToDate = 0x00 OutOfDate = 0x10 } [Flags()] enum ProductFlags { SignatureStatus = 0x000000F0 ProductState = 0x0000F000 } # Fetch installed AV products $antivirusProducts = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct if (-not $antivirusProducts) { Write-Host "No antivirus detected in SecurityCenter2! Please verify manually." exit 1 } # Group AVs by displayName $groupedAVs = $antivirusProducts | Group-Object -Property displayName # Initialize AV status check $avFound = $false $avResults = @() foreach ($group in $groupedAVs) { $avName = $group.Name $instances = $group.Group # Initialize merged status $isEnabled = $false $isUpToDate = $false $avOutput = "`n$avName" foreach ($av in $instances) { $productState = $av.productState # Extract "Status" (Enabled/Disabled) using bitwise AND $currentState = [ProductState]($productState -band [ProductFlags]::ProductState) $currentStatus = if ($currentState -eq [ProductState]::On) { "Enabled" } else { "Disabled" } # Extract "Definition Status" using bitwise AND $currentSignatureStatus = [SignatureStatus]($productState -band [ProductFlags]::SignatureStatus) $currentDefinitionStatus = if ($currentSignatureStatus -eq [SignatureStatus]::UpToDate) { "UpToDate" } else { "OutOfDate" } # Merge instances: AV is considered "Enabled" if any instance is enabled if ($currentStatus -eq "Enabled") { $isEnabled = $true } # Merge instances: AV is considered "UpToDate" if any instance is up to date if ($currentDefinitionStatus -eq "UpToDate") { $isUpToDate = $true } } # Final decision for this AV $finalStatus = if ($isEnabled) { "Enabled" } else { "Disabled" } $finalDefinitionStatus = if ($isUpToDate) { "UpToDate" } else { "OutOfDate" } $avOutput += "`n - Status: $finalStatus" $avOutput += "`n - Definitions: $finalDefinitionStatus" # Check if AV is enabled and up-to-date if ($finalStatus -eq "Enabled" -and $finalDefinitionStatus -eq "UpToDate") { $avFound = $true } # Store the AV results to display later $avResults += $avOutput } # Print summary message first if ($avFound) { Write-Host "At least one antivirus is enabled and up-to-date." } else { Write-Host "No active and up-to-date antivirus detected! Please check your AV software." } # Print the detailed AV results $avResults | ForEach-Object { Write-Host $_ } # Exit with appropriate status code if (-not $avFound) { exit 1 } exit 0 # Success ```
Author
Owner

@bbrendon commented on GitHub (Feb 28, 2025):

I don't think i've seen two from the same brand, but I know I've removed webroot and it still appears. What I've done is just wipe the AV center and reboot. It rebuilds itself.

<!-- gh-comment-id:2689476373 --> @bbrendon commented on GitHub (Feb 28, 2025): I don't think i've seen two from the same brand, but I know I've removed webroot and it still appears. What I've done is just wipe the AV center and reboot. It rebuilds itself.
Author
Owner

@SpookOz commented on GitHub (Mar 3, 2025):

Yeah I've seen it with BitDefender and Vipre. Rebuilding sounds like a good method. How do you wipe the AV center?

<!-- gh-comment-id:2693131735 --> @SpookOz commented on GitHub (Mar 3, 2025): Yeah I've seen it with BitDefender and Vipre. Rebuilding sounds like a good method. How do you wipe the AV center?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/community-scripts#319
No description provided.