void InstalledPackages::refresh(DBRepository *rep, Job *job, bool detectMSI) { rep->currentRepository = 10000; // no direct usage of "data" here => no mutex /* Example: 0 : 0 ms 1 : 0 ms 2 : 143 ms 3 : 31 ms 4 : 5 ms 5 : 199 ms 6 : 3365 ms 7 : 378 ms 8 : 644 ms */ HRTimer timer(9); timer.time(0); // qDebug() << "InstalledPackages::refresh.0"; if (!job->isCancelled() && job->getErrorMessage().isEmpty()) { Job* sub = job->newSubJob(0.2, QObject::tr("Detecting directories deleted externally")); QList<InstalledPackageVersion*> ipvs = getAll(); for (int i = 0; i < ipvs.count(); i++) { InstalledPackageVersion* ipv = ipvs.at(i); if (ipv->installed()) { QDir d(ipv->getDirectory()); d.refresh(); if (!d.exists()) { QString err = this->setPackageVersionPath( ipv->package, ipv->version, ""); if (!err.isEmpty()) job->setErrorMessage(err); } } } qDeleteAll(ipvs); sub->completeWithProgress(); } timer.time(1); if (!job->isCancelled() && job->getErrorMessage().isEmpty()) { Job* sub = job->newSubJob(0.6, QObject::tr("Reading registry package database")); QString err = readRegistryDatabase(); if (!err.isEmpty()) job->setErrorMessage(err); sub->completeWithProgress(); } timer.time(2); if (job->shouldProceed()) { Job* sub = job->newSubJob(0.02, QObject::tr( "Correcting installation paths created by previous versions of Npackd")); QString windowsDir = WPMUtils::normalizePath(WPMUtils::getWindowsDir()); QList<InstalledPackageVersion*> ipvs = this->getAll(); for (int i = 0; i < ipvs.count(); i++) { InstalledPackageVersion* ipv = ipvs.at(i); if (ipv->installed()) { QString d = WPMUtils::normalizePath(ipv->directory); // qDebug() << ipv->package <<ipv->directory; if ((WPMUtils::isUnder(d, windowsDir) || WPMUtils::pathEquals(d, windowsDir)) && ipv->package != packageName) { this->setPackageVersionPath(ipv->package, ipv->version, ""); } } } qDeleteAll(ipvs); sub->completeWithProgress(); } // adding well-known packages should happen before adding packages // determined from the list of installed packages to get better // package descriptions for com.microsoft.Windows64 and similar packages if (job->shouldProceed()) { Job* sub = job->newSubJob(0.03, QObject::tr("Adding well-known packages"), true, true); AbstractThirdPartyPM* pm = new WellKnownProgramsThirdPartyPM( this->packageName); detect3rdParty(sub, rep, pm, false); delete pm; } timer.time(3); if (job->shouldProceed()) { Job* sub = job->newSubJob(0.02, QObject::tr("Setting the NPACKD_CL environment variable")); QString err = rep->updateNpackdCLEnvVar(); if (!err.isEmpty()) job->setErrorMessage(err); else sub->completeWithProgress(); } timer.time(4); // qDebug() << "InstalledPackages::refresh.2"; // detecting from the list of installed packages should happen first // as all other packages consult the list of installed packages. Secondly, // MSI or the programs from the control panel may be installed in strange // locations like "C:\" which "uninstalls" all packages installed by Npackd if (job->shouldProceed()) { Job* sub = job->newSubJob(0.01, QObject::tr("Reading the list of packages installed by Npackd"), true, true); AbstractThirdPartyPM* pm = new InstalledPackagesThirdPartyPM(); detect3rdParty(sub, rep, pm, false); delete pm; } // qDebug() << "InstalledPackages::refresh.2.1"; /* * use DISM API instead if (job->shouldProceed()) { Job* sub = job->newSubJob(0.01, QObject::tr("Detecting Component Based Servicing packages"), true, true); AbstractThirdPartyPM* pm = new CBSThirdPartyPM(); detect3rdParty(sub, rep, pm, true, "cbs:"); delete pm; } */ timer.time(5); if (job->shouldProceed()) { if (detectMSI) { Job* sub = job->newSubJob(0.05, QObject::tr("Detecting MSI packages"), true, true); // MSI package detection should happen before the detection for // control panel programs AbstractThirdPartyPM* pm = new MSIThirdPartyPM(); detect3rdParty(sub, rep, pm, true, "msi:"); delete pm; } else { job->setProgress(job->getProgress() + 0.05); } } timer.time(6); // qDebug() << "InstalledPackages::refresh.3"; if (job->shouldProceed()) { Job* sub = job->newSubJob(0.02, QObject::tr("Detecting software control panel packages"), true, true); AbstractThirdPartyPM* pm = new ControlPanelThirdPartyPM(); detect3rdParty(sub, rep, pm, true, "control-panel:"); delete pm; } timer.time(7); if (job->shouldProceed()) { Job* sub = job->newSubJob(0.05, QObject::tr("Clearing information about installed package versions in nested directories")); QString err = clearPackagesInNestedDirectories(); if (!err.isEmpty()) job->setErrorMessage(err); else { sub->completeWithProgress(); job->setProgress(1); } } timer.time(8); // timer.dump(); // this->mutex.unlock(); job->complete(); }
void InstalledPackages::refresh(DBRepository *rep, Job *job, bool detectMSI) { rep->currentRepository = 10000; // no direct usage of "data" here => no mutex if (job->shouldProceed()) { Job* sub = job->newSubJob(0.2, QObject::tr("Detecting directories deleted externally")); QList<InstalledPackageVersion*> ipvs = getAll(); for (int i = 0; i < ipvs.count(); i++) { InstalledPackageVersion* ipv = ipvs.at(i); if (ipv->installed()) { QDir d(ipv->getDirectory()); d.refresh(); if (!d.exists()) { QString err = this->setPackageVersionPath( ipv->package, ipv->version, ""); if (!err.isEmpty()) job->setErrorMessage(err); } } } qDeleteAll(ipvs); sub->completeWithProgress(); } if (job->shouldProceed()) { Job* sub = job->newSubJob(0.6, QObject::tr("Reading registry package database")); QString err = readRegistryDatabase(); if (!err.isEmpty()) job->setErrorMessage(err); sub->completeWithProgress(); } if (job->shouldProceed()) { Job* sub = job->newSubJob(0.02, QObject::tr( "Correcting installation paths created by previous versions of Npackd")); QString windowsDir = WPMUtils::normalizePath(WPMUtils::getWindowsDir()); QList<InstalledPackageVersion*> ipvs = this->getAll(); for (int i = 0; i < ipvs.count(); i++) { InstalledPackageVersion* ipv = ipvs.at(i); if (ipv->installed()) { QString d = WPMUtils::normalizePath(ipv->directory); // qDebug() << ipv->package <<ipv->directory; if ((WPMUtils::isUnder(d, windowsDir) || WPMUtils::pathEquals(d, windowsDir)) && ipv->package != InstalledPackages::packageName) { this->setPackageVersionPath(ipv->package, ipv->version, ""); } } } qDeleteAll(ipvs); sub->completeWithProgress(); } // adding well-known packages should happen before adding packages // determined from the list of installed packages to get better // package descriptions for com.microsoft.Windows64 and similar packages // detecting from the list of installed packages should happen first // as all other packages consult the list of installed packages. Secondly, // MSI or the programs from the control panel may be installed in strange // locations like "C:\" which "uninstalls" all packages installed by Npackd // MSI package detection should happen before the detection for // control panel programs if (job->shouldProceed()) { QList<AbstractThirdPartyPM*> tpms; tpms.append(new WellKnownProgramsThirdPartyPM( InstalledPackages::packageName)); tpms.append(new InstalledPackagesThirdPartyPM()); tpms.append(new MSIThirdPartyPM()); // true, msi: tpms.append(new ControlPanelThirdPartyPM()); // true, control-panel: QStringList jobTitles; jobTitles.append(QObject::tr("Adding well-known packages")); jobTitles.append(QObject::tr("Reading the list of packages installed by Npackd")); jobTitles.append(QObject::tr("Detecting MSI packages")); jobTitles.append(QObject::tr("Detecting software control panel packages")); QStringList prefixes; prefixes.append(""); prefixes.append(""); prefixes.append("msi:"); prefixes.append("control-panel:"); QList<Repository*> repositories; QList<QList<InstalledPackageVersion*>* > installeds; for (int i = 0; i < tpms.count(); i++) { repositories.append(new Repository()); installeds.append(new QList<InstalledPackageVersion*>()); } QList<QFuture<void> > futures; for (int i = 0; i < tpms.count(); i++) { AbstractThirdPartyPM* tpm = tpms.at(i); Job* s = job->newSubJob(0.1, jobTitles.at(i), false, true); QFuture<void> future = QtConcurrent::run( tpm, &AbstractThirdPartyPM::scan, s, installeds.at(i), repositories.at(i)); futures.append(future); } for (int i = 0; i < futures.count(); i++) { futures[i].waitForFinished(); job->setProgress(0.82 + (i + 1.0) / futures.count() * 0.05); } for (int i = 0; i < futures.count(); i++) { Job* sub = job->newSubJob(0.1, QObject::tr("Detecting %1").arg(i), false, true); detect3rdParty(sub, rep, repositories.at(i), *installeds.at(i), i == 2 || i == 3, prefixes.at(i)); job->setProgress(0.87 + (i + 1.0) / futures.count() * 0.05); } qDeleteAll(repositories); qDeleteAll(installeds); qDeleteAll(tpms); } if (job->shouldProceed()) { Job* sub = job->newSubJob(0.02, QObject::tr("Setting the NPACKD_CL environment variable")); QString err = rep->updateNpackdCLEnvVar(); if (!err.isEmpty()) job->setErrorMessage(err); else sub->completeWithProgress(); } /* * use DISM API instead if (job->shouldProceed()) { Job* sub = job->newSubJob(0.01, QObject::tr("Detecting Component Based Servicing packages"), true, true); AbstractThirdPartyPM* pm = new CBSThirdPartyPM(); detect3rdParty(sub, rep, pm, true, "cbs:"); delete pm; } */ // TODO: if (detectMSI) { if (job->shouldProceed()) { Job* sub = job->newSubJob(0.06, QObject::tr("Clearing information about installed package versions in nested directories")); QString err = clearPackagesInNestedDirectories(); if (!err.isEmpty()) job->setErrorMessage(err); else { sub->completeWithProgress(); job->setProgress(1); } } job->complete(); }