windows删除自身文件及目录的方法

函数声明

bool removeMyself(const QString &exeFilePath,const QString &targetDir);

函数实现

bool MainWidget::removeMyself(const QString &exeFilePath, const QString &targetDir)
{
#ifdef Q_OS_WIN
    const QString batchfile = "D:/uninstall.vbs";
    QFile file(batchfile);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        return false;
    }

    const bool removeTargetDir = true; //删除目标目录
    QTextStream batch(&file);
    batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n";
    batch << "file = WScript.Arguments.Item(0)\n";
    batch << "folderpath = WScript.Arguments.Item(1)\n";
    batch << "Set folder = fso.GetFolder(folderpath)\n";
    batch << "on error resume next\n";

    batch << "while fso.FileExists(file)\n";
    batch << "    fso.DeleteFile(file)\n";
    batch << "    WScript.Sleep(1000)\n";
    batch << "wend\n";
    if (!removeTargetDir)
        batch << "if folder.SubFolders.Count = 0 and folder.Files.Count = 0 then\n";
    batch << "    Set folder = Nothing\n";
    batch << "    fso.DeleteFolder folderpath, true\n";
    if (!removeTargetDir)
        batch << "end if\n";
    batch << "fso.DeleteFile(WScript.ScriptFullName)\n";

    file.close();

    QStringList arguments;
    arguments << QLatin1String("//Nologo") << batchfile; // execute the batchfile
    arguments << exeFilePath; //卸载exe文件路径 如:D:/wechat/maintenancetool.exe
    arguments << targetDir; //卸载目录路径 如:D:/wechat

    return QProcess::startDetached(QLatin1String("cscript"), arguments, QDir::rootPath());
#endif
}

函数调用

auto isok = removeMyself("D:/wechat/maintenancetool.exe","D:/wechat");
qDebug() << "isok = " << isok;

代码来源说明,这段代码来自Qt Installer Framework,在我学习Qt Installer Framework源代码时,提取出来的,因为我也一直想知道如何在windows中删除自身及目录,特别是在想实现自定义卸载软件时需要用到,Qt官方也在代码里吐槽了windows,不能删除自身文件,所以使用了一种比较脏的方法,不管脏不脏,能达到目的,就行了。

如下是Qt源代码

void PackageManagerCorePrivate::deleteMaintenanceTool()
{
    QDir resourcePath(QFileInfo(maintenanceToolName()).dir());
    resourcePath.remove(QLatin1String("installer.dat"));
    QDir installDir(targetDir());
    installDir.remove(m_data.settings().maintenanceToolName() + QLatin1String(".dat"));
    installDir.remove(QLatin1String("network.xml"));
    installDir.remove(m_data.settings().maintenanceToolIniFile());
    QInstaller::VerboseWriter::instance()->setFileName(QString());
    installDir.remove(m_core->value(QLatin1String("LogFileName"), QLatin1String("InstallationLog.txt")));
#ifdef Q_OS_WIN
    // Since Windows does not support that the maintenance tool deletes itself we have to go with a rather dirty hack. 
    // What we do is to create a batchfile that will try to remove the maintenance tool once per second. Then
    // we start that batchfile detached, finished our job and close ourselves. Once that's done the batchfile
    // will succeed in deleting our uninstall.exe and, if the installation directory was created but us and if
    // it's empty after the uninstall, deletes the installation-directory.
    const QString batchfile = QDir::toNativeSeparators(QFileInfo(QDir::tempPath(),
        QLatin1String("uninstall.vbs")).absoluteFilePath());
    QFile f(batchfile);
    if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
        throw Error(tr("Cannot prepare removal"));

    const bool removeTargetDir = QVariant(m_core->value(scRemoveTargetDir)).toBool();
    QTextStream batch(&f);
    batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n";
    batch << "file = WScript.Arguments.Item(0)\n";
    batch << "folderpath = WScript.Arguments.Item(1)\n";
    batch << "Set folder = fso.GetFolder(folderpath)\n";
    batch << "on error resume next\n";

    batch << "while fso.FileExists(file)\n";
    batch << "    fso.DeleteFile(file)\n";
    batch << "    WScript.Sleep(1000)\n";
    batch << "wend\n";
    if (!removeTargetDir)
        batch << "if folder.SubFolders.Count = 0 and folder.Files.Count = 0 then\n";
    batch << "    Set folder = Nothing\n";
    batch << "    fso.DeleteFolder folderpath, true\n";
    if (!removeTargetDir)
        batch << "end if\n";
    batch << "fso.DeleteFile(WScript.ScriptFullName)\n";

    f.close();

    QStringList arguments;
    arguments << QLatin1String("//Nologo") << batchfile; // execute the batchfile
    arguments << QDir::toNativeSeparators(QFileInfo(installerBinaryPath()).absoluteFilePath());
    arguments << targetDir();

    if (!QProcessWrapper::startDetached(QLatin1String("cscript"), arguments, QDir::rootPath()))
        throw Error(tr("Cannot start removal"));
#else
    // every other platform has no problem if we just delete ourselves now
    QFile maintenanceTool(QFileInfo(installerBinaryPath()).absoluteFilePath());
    maintenanceTool.remove();
# ifdef Q_OS_MACOS
    if (QInstaller::isInBundle(installerBinaryPath())) {
        const QLatin1String cdUp("/../../..");
        removeDirectoryThreaded(QFileInfo(installerBinaryPath() + cdUp).absoluteFilePath());
        QFile::remove(QFileInfo(installerBinaryPath() + cdUp).absolutePath()
            + QLatin1String("/") + configurationFileName());
    } else
# endif
#endif
    {
        // finally remove the components.xml, since it still exists now
        QFile::remove(QFileInfo(installerBinaryPath()).absolutePath() + QLatin1String("/")
            + configurationFileName());
    }
}

其中的英文注释翻译中文是这样说的,

//由于Windows不支持维护工具自动删除,我们不得不采用一种相当肮脏的方法。
//我们要做的是创建一个批处理文件,它将尝试每秒删除一次维护工具。然后
//我们开始分离批处理文件,完成我们的工作并关闭自己。一旦完成了批处理文件
//将成功删除我们的uninstall.exe和,如果安装目录是创建的,但我们和if .exe
//卸载后为空,删除安装目录。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值