问题概述:
今天在实际开发中遇到一个问题;要求是检测电脑是否安装某个驱动,如果没有安装提示用户安装;开始就想到了QDir来遍历指定C://Windows//System32//drivers//下的所有以.sys结尾的文件,然后比对文件名。代码也很简单,但是在实际中却发现已经存在了对应的驱动后,仍然是提示未找到,后来发现指定的是C://Windows//System32//drivers;但是实际遍历访问的是 C://Windows//SysWOW64//drivers下的文件;于是开始百度大法,最终知道了问题所在:
问题所在
由于我的Qt编译器是32位的,但是操作系统是win7 64位的,32位程序在访问C://Windows//System32目录时,被系统重定向到 C://windows//SysWOW64目录下,自然获取到的文件也不是预期的;至于为什么导致,简单来说,就是微软为了实现64位操作系统兼容32位程序,在System32目录下特地创建了SysWOW64目录目录来存放32位程序运行需要的一些必要文件(动态库文件,驱动安装文件,安装信息文件,配置文件),当32位程序访问System32目录时就会被系统重定向到SysWOW64目录
解决方法
既然知道了问题所在,那么就着手解决,主要思路如下:首先判断当前电脑的操作系统->遍历System32位目录->do Something
1.判断电脑的操作系统位数
bool DataMonitor::is64bitOperatorSystem()
{
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
PGNSI pGNSI;
SYSTEM_INFO si;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
pGNSI =(PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
if (pGNSI)
{
pGNSI(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 /*||
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64*/)
{
return true;
}
}
return false;
}
2.遍历System32/driver
bool checkDriverIsUninstall()
{
//由于程序是32位的,操作系统是64位的,因此windwos/system32目录会被操作系统重定向到windwos/SysWOW64目录,但驱动是32位的,会安装在system32的目录,所以要进行目录重定位
//这个判断逻辑主要是针对 AMD64 IA64两种操作系统,不包含ARM64
if(is64bitOperatorSystem()) //如果是64位操作系统,调用windowsAPI函数来
{
PVOID oldValue = NULL;
bool bRet = ::Wow64DisableWow64FsRedirection(&oldValue); //关闭系统重定向的问题
if(bRet == true)
{
QString startDir = "C:\\Windows\\System32\\drivers\\";
QDir driverDir(startDir);
QStringList nameFilters; //设置要过滤的文件类型
nameFilters<<"*.sys*";
QFileInfoList files = driverDir.entryInfoList(nameFilters,QDir::Files); //查找当前目录下所有后缀名为.sys的可读文件,并以文件名来进行排序
int count=0;
for(int i=0;i<files.size();i++)
{
QFileInfo fileName = files.at(i);
if(fileName.fileName().toUpper() == "VIRTPORT.SYS" || fileName.fileName().toUpper() == "VIRTBUS.SYS")
{
isFind = true;
}
}
}
::Wow64RevertWow64FsRedirection(oldValue); //重新恢复系统
}
return isFind;
}