检测系统中的杀毒软件(.NET)

首先要说明两个概念:
1. Windows Security Center
这个东西的概念似乎是从Vista开始的。反正就是整合了防火墙,系统更新,防毒软件等等的综合平台。

2.

Windows 管理规范(Windows Management Instrumentation)是一项核心的 Windows 管理技术;用户可以使用 WMI 管理本地和远程计算机。WMI 通过编程和脚本语言为日常管理提供了一条连续一致的途径。例如,用户可以:
• 在远程计算机器上启动一个进程。
• 设定一个在特定日期和时间运行的进程。
• 远程启动计算机。
• 获得本地或远程计算机的已安装程序列表。
• 查询本地或远程计算机的 Windows 事件日志。
 
形象地比喻,就好似汽车仪表盘

察看系统的WMI,可以通过管理员身份打开命令行,输入wbemtest,就可以看到:


如果要通过.NET的程序方法获得系统中的杀毒软件,最方便的是通过WMI,查询root\SecurityCenter。
代码如下:

string strWMIPath = @"\\" + Environment.MachineName + @"\root\SecurityCenter";
try
{
    ManagementObjectSearcher searcher 
= new ManagementObjectSearcher(strWMIPath, "SELECT * FROM AntivirusProduct");
    ManagementObjectCollection instances 
= searcher.Get();
    
foreach (ManagementObject queryObj in instances)
    {
        Console.WriteLine(queryObj[
"instanceGuid"].ToString());
    }
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}
但实际中似乎可能碰到这种问题:
杀毒软件已经卸载,但依然能被查询到。
原因可能有多种,比如WMI损坏,或者杀毒软件的设计就是不删除(好像BitDefender是这样,附一张BitDefender的乌龙图:

)。
简单的方法就是手动在wbemtest中删除,但毕竟不是个普适的办法。

但我们可以发现Windows Security Center中是不会有这种乌龙的。

其原因就是Windows Security Center是用了双层检测方法。一层是手动检测,另外一层是通过WMI。手动检测模式下,Windows Security Center搜索注册表键值和第三方厂商提供给微软的文件来鉴别。WMI模式下,软件生产厂商判断它们的产品运行状态,通过WMI Provider回报给Windows Security Center。

于是我们可以通过察看HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall,来判断是否是一个已经安装的软件:


public void getInstalledSWList()
{
    Microsoft.Win32.RegistryKey regKey 
= Microsoft.Win32.Registry.LocalMachine;
    Microsoft.Win32.RegistryKey subKey1 
= regKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
    
string[] subKeyNames = subKey1.GetSubKeyNames();

    
foreach (string subKeyName in subKeyNames)
    {
        Microsoft.Win32.RegistryKey subKey2 
= subKey1.OpenSubKey(subKeyName);

        
if (ValueNameExists(subKey2.GetValueNames(), "DisplayName"&& ValueNameExists(subKey2.GetValueNames(), "DisplayVersion"))
        {
           
//Get the installed software list in windows through subKey2.GetValue("DisplayName").ToString()
        }
        subKey2.Close();
    }
    subKey1.Close();
}



private bool ValueNameExists(string[] valueNames, string valueName)
{
    
foreach (string s in valueNames)
    {
        
if (s.ToLower() == valueName.ToLower()) return true;
    }

    
return false;
}


这样解决方案就比较完备了。

WMI的功能似乎还是挺强大的。
原文地址:https://www.cnblogs.com/galaxyyao/p/1567383.html