Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <# Version 1.0.8
- .DESCRIPTION
- Test the health of the Bitdefender Endpoint Security Tools.
- This function will check Bitdefender
- * is installed
- * is service healthy
- * is up to date
- * aggregate health of above checks
- * signature version
- * signature number
- * signature published date
- * signature update time
- .EXAMPLE
- IsBitdefenderInstalled : True
- IsBitdefenderServiceHealthy : True
- IsBitdefenderUptodate : True
- IsBitdefenderHealthy : True
- SignatureVersion : 7.72508
- SignatureNumber : 9697199
- SignatureDate : 7/26/2017 8:03:50 AM
- SignatureUpdateTime : 7/26/2017 7:54:59 AM
- .NOTES
- Created by: Jason Wasser @wasserja https://www.powershellgallery.com/packages/BitdefenderHealth/
- Last updated by creator: v1.0.5 7/26/2017
- Modified by Isaac Good:
- v1.0.9 - 9/1/2025
- Fixed - Added $TimeZone to Get-BitdefenderUpdateFileData to fix ConvertTimeBySystemTimeZoneId error
- v1.0.8 - 4/6/2023
- Added - Conversion of SignatureUpdateTime from UTC to local time to match SignatureDate
- Changed - minor code formatting cleanup, spelling correction in comments
- v1.0.7 - 2/20/2022
- Added - triggering of update process if outdated
- Added - closing of Syncro alert if healthy
- Changed - consolidated path references to variables
- Changed - improved verbose output, misc code cleanup and simplification
- Removed - process running check (redundant as we already check the services)
- v1.0.6 - 5/3/2021
- Added - delay if recent kernel power event
- Added - alerting for Syncro
- Changed - bundled all functions into one script for use via RMM
- Changed - service status to check all services not just one
- Fixed - errors caused by multiple files returned using wildcards
- Removed - remote computer connection code/references not needed for use via RMM
- Removed - non-working component monitoring (Product.ActionCenter.conf no longer exists)
- #>
- Import-Module $env:SyncroModule -DisableNameChecking
- $BitdefenderPath = "$env:programfiles\Bitdefender\Endpoint Security"
- $BitdefenderThreatScannerPath = "$BitdefenderPath\ThreatScanner"
- # Check for a recent kernel power event and if found, give BD time to update
- $LastKPE = Get-EventLog -LogName "System" -Source "Microsoft-Windows-Kernel-Power" -Newest 1 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty TimeGenerated
- if ($LastKPE) {
- $recent = (New-TimeSpan -Start $LastKPE -End (Get-Date)).TotalMinutes -le 15
- Write-Verbose -Message "Recent kernel power event found: $Recent"
- if ($Recent) {
- Start-Sleep -Seconds 900 # 15 minutes
- }
- }
- function Convert-UnixTimeToDateTime {
- [CmdletBinding()]
- param (
- [Parameter(Mandatory = $true)]
- [int]$UnixTime
- )
- $UnixConvertedDateTime = (New-Object DateTime(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc)).AddSeconds($UnixTime)
- Write-Verbose "Unix converted date time: $UnixConvertedDateTime"
- $UnixConvertedDateTime
- }
- function Convert-TimeZone {
- [CmdletBinding()]
- param (
- [datetime]$inputDateTime = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'),
- [string]$fromTimeZone = "E. Europe Standard Time",
- [string]$toTimeZone = [System.TimeZoneInfo]::Local.Id
- )
- begin {
- function Test-TimeZone {
- param (
- $TimeZone
- )
- $ValidTimeZones = [System.TimeZoneInfo]::GetSystemTimeZones()
- Write-Verbose -Message "Validating time zone: $TimeZone"
- $IsValidTimeZone = ($ValidTimeZones | Select-Object -ExpandProperty Id) -contains $TimeZone
- Write-Verbose -Message "Timezone $TimeZone is $IsValidTimeZone"
- $IsValidTimeZone
- }
- }
- process {
- # Validate time zones
- if ((Test-TimeZone -TimeZone $fromTimeZone) -and (Test-TimeZone -TimeZone $toTimeZone)) {
- Write-Verbose -Message "Timezones have been validated"
- Write-Verbose -Message "Converting '$inputDateTime' from '$fromTimeZone' to '$toTimeZone'"
- $outputDateTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($inputDateTime, $fromTimeZone, $toTimeZone)
- Write-Verbose -Message "Converted time: $outputDateTime"
- $outputDateTime
- } else {
- Write-Error "Invalid time zone entered"
- }
- }
- }
- function Test-BitdefenderService {
- [CmdletBinding()]
- param (
- [string]$ServiceName
- )
- try {
- $Service = Get-Service -Name $ServiceName -ErrorAction Stop
- if ($Service) {
- $ServiceDetails = Get-WmiObject -Class win32_service -Filter "Name = '$ServiceName'"
- $ServiceHealthProperties = @{
- Name = $Service.Name
- ServiceExists = $true
- IsRunning = [bool]($Service.Status -eq 'Running')
- IsAutomatic = [bool]($ServiceDetails.StartMode -eq 'Auto')
- }
- $ServiceHealth = New-Object -TypeName PSCustomObject -Property $ServiceHealthProperties
- Write-Verbose -Message "Validated service: $($ServiceHealth.Name)"
- $ServiceHealth
- }
- } catch {
- $ServiceHealthProperties = @{
- Name = $ServiceName
- ServiceExists = $false
- IsRunning = $false
- IsAutomatic = $false
- }
- $ServiceHealth = New-Object -TypeName PSCustomObject -Property $ServiceHealthProperties
- Write-Error -Message "Service Issue: $ServiceHealth"
- $ServiceHealth
- }
- }
- function Get-BitdefenderSignatureDate {
- [CmdletBinding()]
- param (
- $TimeZone = [System.TimeZoneInfo]::Local.Id
- )
- process {
- try {
- $BitdefenderUpdatePath = Get-Item -Path "$BitdefenderThreatScannerPath\Antivirus*\versions.id*" | Sort-Object LastWriteTime | Select-Object -Last 1
- [xml]$BitdefenderVersionsFile = Get-Content -Path $BitdefenderUpdatePath
- # Bitdefender headquarters is in Eastern European Time Zone which also has daylight saving time.
- $BitdefenderSignatureDate = Convert-TimeZone -inputDateTime ([datetime]$BitdefenderVersionsFile.info.time.'#text') -fromTimeZone 'E. Europe Standard Time' -toTimeZone $TimeZone
- $BitdefenderSignatureDate
- } catch {
- Write-Warning -Message "Unable to determine the signature date."
- $BitdefenderSignatureDate = $null
- $BitdefenderSignatureDate
- }
- }
- }
- function Get-BitdefenderUpdateFileData {
- [CmdletBinding()]
- param (
- $TimeZone = [System.TimeZoneInfo]::Local.Id
- )
- process {
- $BitdefenderUpdatePath = Get-Item -Path "$BitdefenderThreatScannerPath\Antivirus*\Plugins\Update.txt" | Sort-Object LastWriteTime | Select-Object -Last 1
- $UpdateFile = Get-Content -Path $BitdefenderUpdatePath
- $BitdefenderUpdateFileDataProperties = ''
- $BitdefenderUpdateFileDataProperties = @{}
- foreach ($Line in $UpdateFile) {
- $BitdefenderUpdateFileDataProperties.Add(($Line.Split(':')[0]).Trim(), ($Line.Substring($Line.IndexOf(':') + 1)).Trim())
- }
- # Changing Update time to [datetime]
- $BitdefenderUpdateFileDataProperties['Update time'] = (Convert-UnixTimeToDateTime -UnixTime $BitdefenderUpdateFileDataProperties['Update time GMT'])
- # Converting GMT to local time
- $BitdefenderUpdateFileDataProperties['Update time'] = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId( $BitdefenderUpdateFileDataProperties['Update time'], 'UTC', $TimeZone)
- $BitdefenderUpdateFileData = New-Object -TypeName PSCustomObject -Property $BitdefenderUpdateFileDataProperties
- $BitdefenderUpdateFileData
- }
- }
- function Test-Bitdefender {
- [CmdletBinding()]
- param (
- )
- process {
- try {
- # Is Bitdefender Installed
- $IsBitdefenderInstalled = Test-Path -Path $BitdefenderPath
- if ($IsBitdefenderInstalled) {
- Write-Verbose -Message "Bitdefender is installed at: $BitdefenderPath"
- # Are Bitdefender Services Running and Automatically Started
- $BitdefenderServiceNames = @((Get-Service | Where-Object { $_.DisplayName -like "*bitdef*" }).Name)
- foreach ($BitdefenderServiceName in $BitdefenderServiceNames) {
- $BitdefenderService = Test-BitdefenderService $BitdefenderServiceName
- $IsBitdefenderServiceHealthy = $BitdefenderService.ServiceExists -and $BitdefenderService.IsRunning -and $BitdefenderService.IsAutomatic
- if ($IsBitdefenderServiceHealthy -eq $false) {
- $IsBitdefenderServiceHealthyOverAll = $false
- } else { $IsBitdefenderServiceHealthyOverAll = $true }
- }
- # Is Bitdefender up to date
- $BitdefenderSignatureDate = Get-BitdefenderSignatureDate
- $BitdefenderUpdateFileData = Get-BitdefenderUpdateFileData
- if ($BitdefenderSignatureDate) {
- $IsBitdefenderUpToDate = (New-TimeSpan -Start $BitdefenderSignatureDate -End (Get-Date)).TotalDays -le 1
- # If not, trigger update process, wait and retry
- if (-not $IsBitdefenderUpToDate) {
- &"$BitdefenderPath\product.console.exe" /c StartUpdate | Out-Null
- Start-Sleep 900 # wait 15 minutes
- #check for newer modification date
- $BitdefenderSignatureDate = Get-BitdefenderSignatureDate
- $IsBitdefenderUpToDate = (New-TimeSpan -Start $BitdefenderSignatureDate -End (Get-Date)).TotalDays -le 1
- }
- } else {
- $IsBitdefenderUpToDate = (New-TimeSpan -Start $BitdefenderUpdateFileData.'Update time' -End (Get-Date)).TotalDays -le 1
- }
- } else {
- Write-Warning "Unable to find $BitdefenderPath"
- $IsBitdefenderServiceHealthyOverall = $false
- $IsBitdefenderUpToDate = $false
- }
- # Creating Object
- $BitdefenderStatusProperties = [ordered]@{
- IsBitdefenderInstalled = $IsBitdefenderInstalled
- IsBitdefenderServiceHealthy = $IsBitdefenderServiceHealthyOverall
- IsBitdefenderUpToDate = $IsBitdefenderUpToDate
- IsBitdefenderHealthy = $IsBitdefenderInstalled -and $IsBitdefenderServiceHealthy -and $IsBitdefenderUpToDate
- SignatureVersion = $BitdefenderUpdateFileData.Version
- SignatureNumber = $BitdefenderUpdateFileData.'Signature Number'
- SignatureDate = $BitdefenderSignatureDate
- SignatureUpdateTime = $BitdefenderUpdateFileData.'Update time'
- }
- $BitdefenderStatus = New-Object -TypeName PSCustomObject -Property $BitdefenderStatusProperties | Out-String
- $BitdefenderStatus
- # Clear Variables
- $BitdefenderUpdateFileData = $null
- $BitdefenderSignatureDate = $null
- # Alert on False conditions
- $Status = $BitdefenderStatus -Join '|'
- if ($Status -match 'false') {
- RMM-Alert -Category 'Monitor - Bitdefender' -Body "$BitdefenderStatus"
- exit 1
- } else {
- Close-Rmm-Alert -Category "Monitor - Bitdefender"
- }
- } catch {
- Write-Error -Message $_.Exception
- }
- }
- }
- Test-Bitdefender
Advertisement
Add Comment
Please, Sign In to add comment