# How can I determine whether an Antivirus product is installed?

We have a large installation with over 15,000 machines. They are supposed to have a version of Trend Micro installed; however, we don't know that for sure.

These are all Windows boxes which includes XP with various SP levels, Vista both RTM and SP1, and several 2000 and 2003 servers.

How can I determine:

1. Whether ANY AV product is installed?
2. What version of the product is installed?
3. What version of the pattern file is on the box?

Ideas?

Thanks,

-

Since you're talking of 15,000 hosts, querying each of them from the network is going to be highly inefficient.

The Right Thing To Do™ then is to have a watchdog running on each host to make sure the appropriate software is installed and running. This watchdog might be a piece of software running as a service, a scheduled script or even hardware-based if you use something like Intel vPro.

To verify if an AV software is installed, you could use the following PowerShell command --

$avSoftware = get-wmiobject -class "Win32_Product" -namespace "root\cimv2"  -computername "." -filter "Name like '%antivirus%'"  Note that at the end you have a filter argument that you can customize to make sure you're looking at the right product. After playing a bit with the like operator, you should be able to nail the antivirus description and minor variations here and there. Note that my example above (anything containing the word "antivirus") is pretty simplistic. You should instead look for specific patterns matching your approved antivirus software (e.g. "Trend Micro Antivirus%") Anyway, the command above will return a collection of installed products that match your filter statement. From here you can test whether $avSoftware.Count is greater than zero, in which case you have antivirus software installed. The example below lists all the installed antivirus software --

if ($avSoftware.Count -gt 0) { foreach ($av in $avSoftware) { write-host$p.Name
}
} else {
write-host "No AV software found"
}


Instead of just printing a message saying that no AV has been found, you should obviously do something more useful, e.g.

• Install an AV from the network

You also said you'd like to get the version of the installed AV. To do that, you can use the Version property of the Win32_Process. Let's modify the above code like this to also print the version numbers for the installed software --

$avSoftware = get-wmiobject -class "Win32_Product" -namespace "root\cimv2"  -computername "." -filter "Name like '%antivirus%'" foreach ($av in $avSoftware) { write-host$av.Name, $av.Version }  As for the version of the installed virus definition files, you'd have to rely on each specific AV WMI interface. You'll have to consult the vendor's documentation for that. One more thing to remember. It's probably not enough to know that the host has AV installed if the AV isn't running. After checking which AV is installed, you should make sure its process is running. To do that, you'll have to know what the appropriate process for each of your AV software is and look for them like this -- $processes = get-wmiobject -class "Win32_Process" -namespace "root\cimv2" 
-computername "." -filter "Name = 'TeaTimer.exe'"

if ($processes.Count -gt 0) { foreach ($p in $processes) { write-host$p.Name
} else {
# AV not running. Launch it here or notify someone
}


The above example looks for the Spybot process (not exactly AV, but you get the picture), which is called "TeaTimer.exe". Modify it to look for your process instead.

Now, all of that said, if you're dealing with thousands of hosts like that, you should probably invest in some management tool (e.g. LANdesk, Microsoft System Center or Level Platforms.) These tools would make your life a whole lot easier.

-
I think this is pretty close to what I want to do. Thanks, –  Chris Lively May 27 '09 at 17:07

Since you mention Trend Micro, and we use Trend, here's what we do. A scheduled task does a full scan of the system and puts the results in a text file. Actually, it's a log file with the date as the name of the file... like 20090517.log in the C:\TRENDMICRO folder. Because this just has the results of the scan in it, it's a small file.

In our case with roughly 100 computers, it's easy enough for a powershell script on the server to walk through all the computers, and concatenate those files, and only look for the ones that didn't have the string "Virus found count(0)" in them. Obviously if that file and phrase isn't there, something is wrong: AV didn't run recently, Virus found, AV not installed, etc. You probably need something a little more fancy to scale it up.

But aren't there enterprise versions of AV that do it all for you instead of my poor man's version?

-
Interesting idea; but at this scale that might take quite a bit of time. Also, some of our machines run in a disconnected state so I can't be sure of when they will be online. –  Chris Lively May 27 '09 at 17:01
Messages like "No viruses found" don't mean that there are no viruses... It may happen also if AV signatures are too old. –  Sarge Borsch Oct 10 '13 at 6:45

+1 for Knox regarding the enterprise version. I agree. Trend's enterprise desktop solution has a server piece that keeps track of clients and which scan engines and patterns they currently have. It also lets you deploy. I would use this to work toward your goal. Deploy a reinstall of OfficeScan using this. I wouldn't even bother with the effort of deploying scripts to figure out where you're at at this point in the game. Best to just start over. Work with Trend on the licensing if you don't already have the enterprise tools (which would really surprise me). If you don't then someone needs to account for poor purchasing decisions.

-
The problem is that we have a different piece of software (home grown) that we are trying to integrate this data into. The OfficeScan server doesn't seem to allow us to pull the data out of it. –  Chris Lively May 27 '09 at 17:02
Ok, fair enough. Would have been good to note that in your question, just a thought for next time! :) I think, though, that OfficeScan stores its data in a standard db that you should be able to directly interface with. (Don't quote me, though. Going back a little ways on that one.) –  squillman May 27 '09 at 19:55

In current versions of Windows (xp sp3+, vista, win 7) you can query the same WMI provider that Windows Security Center uses to know if an antivirus product installed and up-to-date.

Here's an example:

Set objSWbemServices = GetObject("winmgmts:\\.\root\SecurityCenter")
Set colFirewall = objSWbemServices.ExecQuery("Select * From antivirusProduct",,48)
For Each objAntiVirusProduct In colFirewall
WScript.Echo "companyName: " & objAntiVirusProduct.companyName
WScript.Echo "displayName: " & objAntiVirusProduct.displayName
WScript.Echo "instanceGuid: " & objAntiVirusProduct.instanceGuid
WScript.Echo "onAccessScanningEnabled: " & objAntiVirusProduct.onAccessScanningEnabled
WScript.Echo "productUptoDate: " & objAntiVirusProduct.productUptoDate
WScript.Echo "versionNumber: " & objAntiVirusProduct.versionNumber
Next


That said, not all antivirus products will register a WMI provider, but I suspect most of the popular ones will. Also, it's not clear if this is officially supported by Microsoft, so it might go away in future versions.

You might try it in combination with the other WMI suggestions here, falling back to scanning the installed products if the this doesn't work.

-
My understanding was that this WMI provider was only available on Vista SP1 and that it wasn't going to be in 7. Is that not true? –  Chris Lively May 27 '09 at 17:03
It's not available on Windows 7 unfortunately –  Lucky Luke Dec 6 '12 at 20:53

I would make a logon script that checked for various registry entries or files to determine if a product was installed. Then the script can create a log of machines which do or do not.

Dim WSHShell,strRegKey
Set WSHShell = WScript.CreateObject("WScript.Shell")
strRegKey="HKLM\Software\Symantec\Version"
Wscript.quit(0)

-
The fault with this (or more the AV fault) is when you uninstall some anti-virus for example Norton annoyingly they don't always remove all registry entries thus you could end up with some false results. –  Adam Gibbins May 26 '09 at 23:24
Then also check for the existence of files. –  Jack B Nimble May 27 '09 at 14:00

Not sure how practical this is, given 15,000 hosts, but if you have a listing of the machines you wish to check in a text file, you can query the uninstall key in the registry and parse the results.

Text file named computers.txt with a machine name per line:

COMPUTER1
COMPUTER2


Example named batch.bat:

@echo off

for /F %%i in (computers.txt) do call :SUB %%i

GOTO :EOF

:SUB
echo %1
reg query "\\%1\HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" /s
`

I realize this might be a bit of information overload in text, but it allows you to parse the results for ANY A/V software you're looking for, without knowing the registry entry each product's uninstall information is contained in.

You can also tailor this for specific product registry entries, substituting the registry query for the specific product's registry keys.

-