static bool removeUserChoice(const QString & extension) { QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat); QString FileExtsKey = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.") + extension; if(QSysInfo::WindowsVersion < QSysInfo::WV_VISTA){ //XP RegCU.remove(FileExtsKey + "/Progid"); return true; } QTemporaryFile file; if (file.open()) { QTextStream out(&file); // Unlock Registry, make user 'everyone' can access 'UserChoice' completely. out << "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + extension + "\\UserChoice [7]"; out.flush(); file.flush(); // win7 build-in tool, for user access changing. Require path argument encoded by Unicode. Chinese may cause problem. // Only return after execute completely. QProcess::execute(QString("regini.exe %1").arg(file.fileName())); /// Windows 7, only can remove "/UserChoice" if we own it. remove "/UserChoice/Progid" is forbidden. RegCU.remove(FileExtsKey + "/UserChoice"); return true; } return false; // The QTemporaryFile destructor removes the temporary file // as it goes out of scope. }
bool checkAssociation(const QString & extension) { if(!isSupportAssociation()) return false; #ifndef Q_WS_WIN return false; #else /*! The HKEY_CLASSES_ROOT subtree is a view formed by merging * HKEY_CURRENT_USER\Software\Classes and * HKEY_LOCAL_MACHINE\Software\Classes */ QSettings RegCR("HKEY_CLASSES_ROOT", QSettings::NativeFormat); QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat); QString ext("." + extension); QString ProgID = makeProgID(extension); QString fileName = QFileInfo(qApp->applicationFilePath()).fileName(); QString FileExtsKey = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/") + ext; /// Windows 7:"/UserChoice/Progid" ; XP: "/Progid" QString CurClassId = (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) ? RegCU.value(FileExtsKey + "/UserChoice/Progid").toString() : RegCU.value(FileExtsKey + "/Progid").toString(); QString CurAppId = RegCU.value(FileExtsKey + "/Application").toString(); /// Windows XP bool isRegistered = false; if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT){ if (!CurClassId.isEmpty()) { isRegistered = (CurClassId == ProgID) || (0 == CurClassId.compare(fileName, Qt::CaseInsensitive)) || (0 == CurClassId.compare(QString("Applications\\%1").arg(fileName), Qt::CaseInsensitive)); }else if (!CurAppId.isEmpty()){ //If user uses Open With..., explorer creates it's own ClassId under Application, like "smplayer.exe" isRegistered = (CurAppId == ProgID) || (0 == CurAppId.compare(fileName, Qt::CaseInsensitive)); }else{ //No classId means that no associations exists in Default Programs or Explorer //Check the default per-user association isRegistered = (RegCU.value("Software/Classes/" + ext + REG_DEFAULT).toString() == ProgID); } } //Finally, check the system-wide association //若CurClassId或CurAppId不为空,说明用户在“打开方式”中选择了其他程序,优先级高,会覆盖其他设置。 if (!isRegistered && CurClassId.isEmpty() && CurAppId.isEmpty()) isRegistered = (RegCR.value(ext + REG_DEFAULT).toString() == ProgID); return isRegistered && hasProgID(ProgID); #endif // Q_WS_WIN }
static bool hasProgID(const QString &ProgID) { QSettings RegCR("HKEY_CLASSES_ROOT", QSettings::NativeFormat); QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat); RegCU.beginGroup("Software/Classes"); QString key = ProgID + "/shell/open/command/."; QString appPath = qApp->applicationFilePath(); appPath.replace('/', '\\'); QString expect = QString("\"%1\" \"%2\"").arg(appPath, "%1"); // If it is set file association by this app, the value of key @key will be like this. if (RegCR.childGroups().contains(ProgID)) { return RegCR.value(key).toString() == expect; } else if (RegCU.childGroups().contains(ProgID)) { return RegCU.value(key).toString() == expect; } else { return false; } }
//Associates all extensions in the fileExtensions list with current app. //Returns number of extensions processed successfully. int WinFileAssoc::CreateFileAssociations(const QStringList &fileExtensions) { if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) { return VistaSetAppsAsDefault(fileExtensions); } QSettings RegCR("HKEY_CLASSES_ROOT", QSettings::NativeFormat); //Read only on NT+ QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat); if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError) return 0; if (RegCR.status() != QSettings::NoError) return 0; if (QSysInfo::WindowsVersion < QSysInfo::WV_NT && !RegCR.isWritable()) //Win98 return 0; //Check if classId exists in the registry if (!RegCR.contains(m_ClassId) && !RegCU.contains("Software/Classes/" + m_ClassId)) { //If doesn't exist (user didn't run the setup program), try to create the ClassId for current user. if (!CreateClassId(QApplication::applicationFilePath(), "SMPlayer2 Media Player")) return 0; } int count = 0; foreach(const QString & fileExtension, fileExtensions) { QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension); QString ClassesKeyName = m_ClassId; QString BackupKeyName = ClassesKeyName + "/" + fileExtension; QString CUKeyName = "Software/Classes/." + fileExtension; //Save current ClassId for current user QString KeyVal = RegCU.value(CUKeyName + "/.").toString(); if (KeyVal.length() == 0 || KeyVal == m_ClassId) { //No registered app for this extension for current user. //Check the system-wide (HKEY_CLASSES_ROOT) ClassId for this extension KeyVal = RegCR.value("." + fileExtension + "/.").toString(); } if (KeyVal != m_ClassId) RegCU.setValue(CUKeyName + "/MPlayer_Backup", KeyVal); //Save last ProgId and Application values from the Exts key KeyVal = RegCU.value(ExtKeyName + "/Progid").toString(); if (KeyVal != m_ClassId && KeyVal != m_ClassId2) RegCU.setValue(ExtKeyName + "/MPlayer_Backup_ProgId", KeyVal); KeyVal = RegCU.value(ExtKeyName + "/Application").toString(); if (KeyVal != m_ClassId || KeyVal != m_ClassId2) RegCU.setValue(ExtKeyName + "/MPlayer_Backup_Application", KeyVal); //Create the associations if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) { RegCU.setValue(CUKeyName + "/.", m_ClassId); //Extension class RegCU.setValue(ExtKeyName + "/Progid", m_ClassId); //Explorer FileExt association } else { //Windows ME/98/95 support RegCR.setValue("." + fileExtension + "/.", m_ClassId); } if (RegCU.status() == QSettings::NoError && RegCR.status() == QSettings::NoError) count++; }
bool clearAssociation(const QString & extension) { if(!isSupportAssociation()) return false; #ifdef Q_WS_WIN if(!checkAssociation(extension)) return true; QString ext("." + extension); QString ProgID = makeProgID(extension); QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat); QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat); if (QSysInfo::WindowsVersion < QSysInfo::WV_NT && !RegCR.isWritable()) //Win98 return false; QString fileName = QFileInfo(qApp->applicationFilePath()).fileName(); QString FileExtsKey = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/") + ext; /// Windows 7:"/UserChoice/Progid" ; XP: "/Progid" QString CurClassId = (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) ? RegCU.value(FileExtsKey + "/UserChoice/Progid").toString() : RegCU.value(FileExtsKey + "/Progid").toString(); QString CurAppId = RegCU.value(FileExtsKey + "/Application").toString(); /// Windows XP if (!CurClassId.isEmpty() && ( (CurClassId == ProgID) || (0 == CurClassId.compare(fileName, Qt::CaseInsensitive)) || (0 == CurClassId.compare(QString("Applications\\%1").arg(fileName), Qt::CaseInsensitive)) ) ){ removeUserChoice(extension); } if (!CurAppId.isEmpty() && ( (CurAppId == ProgID) || (0 == CurAppId.compare(fileName, Qt::CaseInsensitive)) ) ){ RegCU.remove(FileExtsKey + "/Application"); } if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT){ if (RegCU.value("Software/Classes/" + ext + REG_DEFAULT).toString() == ProgID) //Only remove if we own it /// This is no recommend to delete in MSDN, case it may cause other problems, such as cannot create new text document if delete '.txt' group. // RegCU.remove("Software/Classes/" + ext); RegCU.remove("Software/Classes/" + ProgID); }else{ //Windows 98 ==> Write to HKCR if (RegCR.value(ext + REG_DEFAULT).toString() == ProgID) // RegCR.remove(ext); RegCR.remove(ProgID); } RegCU.sync(); RegCR.sync(); // SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);// Refresh Explorer cache. return (RegCU.status() == QSettings::NoError && RegCR.status() == QSettings::NoError); #else return false; #endif // Q_WS_WIN }