• QT中QProcess调用命令行的痛苦经历


    在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在QT中通过QProcess类调用命令行的rar.exe来达到效果,但是没想到QProcess类用起来很麻烦,而且达不到效果,折腾了2天仍然没找到原因,使用另外一种办法解决了。

    创建压缩包的方法

    在windows平台创建压缩包,可以直接使用rar.exe,该程序在安装winrar之后,在其安装目录下就可以找到。该程序是winrar对应的命令行版本,其语法例子如下:

    rar.exe a -k -r -s -m1 test.rar direct1/   direct2/  test.txt

    例子对应的目录结构如下:

    s

    上面的命令表示在当前目录下创建压缩包 test.rar ,将当前目录下的 direct1目录以及其所有子目录和文件、direct2目录以及其子目录和文件、当前目录下的文件test.txt 都添加到test.rar压缩包中。

    其中参数a表示添加到压缩包

    参数-r表示递归添加

    命令的问题解决了之后,那么下面就是如何在QT中调用该命令,实际上在QT中调用该命令就出现了很多问题。

    在QT中调用命令行

    QT中调用外部命令一般使用QProcess类提供的成员函数,其使用的具体代码如下:

    QProcess p(0);
    p.start(command,args); //command是要执行的命令,args是参数
    p.waitForFinished();//等待完成
    qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());
    

    套用上面的代码得到如下:

    QProcess p(0);
    QString command = "E:/test_rar_course/rar.exe";
    QStringList args;
    args.append("a");
    args.append("-k");
    args.append("-r");
    args.append("-s");
    args.append("-m1");
    args.append("E:/test_rar_course/test.rar");
    args.append("E:/test_rar_course/direct1/");
    args.append("E:/test_rar_course/direct2/");
    args.append("E:/test_rar_course/test.txt");
    p.execute(command,args);//command是要执行的命令,args是参数
    p.waitForFinished();
    qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());
    

    可以生成test.rar但是,该压缩包中将路径E:/test_rar_course也压缩进去了,而我需要的是打开压缩包之后仅仅看到direct1,direct2,test.txt3个项目,那么是不是设置一下工作目录就可以了呢:

    QProcess p(0);
    p.setWorkingDirectory("E:/test_rar_course/");//指定进程的工作目录
    QString command = "E:/test_rar_course/rar.exe";
    QStringList args;
    args.append("a");
    args.append("-k");
    args.append("-r");
    args.append("-s");
    args.append("-m1");
    args.append("-wE:/test_rar_course/");//指定rar.exe的工作目录
    args.append("test.rar");
    args.append("direct1/");
    args.append("direct2/");
    args.append("test.txt");
    p.execute(command,args);//command是要执行的命令,args是参数
    p.waitForFinished();
    qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());//获取输出
    

    我不仅添加-w参数(该参数为rar.exe的命令行参数,用于指定工作目录)为rar.exe命令指定工作目录,同时利用p.setWorkingDirectory()为启动的进程指定工作目录,运行之后报错,说找不到文件,我猜可能还是工作目录的问题,但是不知道问题在哪里,查了很多资料都无济于事,最终还是放弃了这种尝试,改成了下面的尝试:

    QProcess p(0);
    p.setWorkingDirectory("E:/test_rar_course/");//指定进程的工作目录
    QString command = "E:/test_rar_course/test.bat";
    p.start(command);
    p.waitForFinished();
    qDebug()<<QString::fromLocal8Bit(p.readAllStandardError());
    

    而test.bat的内容为如下:

    cd /d E:/test_rar_course/
    E:/test_rar_course/rar.exe a -k -r -s -m1 -wE:/test_rar_course/ test.rar direct1/ direct2/ test.txt
    

    我直接在bat中通过cd命令切换工作目录,然后进行压缩,其中为了避免出现压缩绝对路径的情况,direct1,direct2,test.txt使用的都是相对路径,直接鼠标双击该test.bat运行OK,放在QT中运行OK,似乎完美的解决了问题。

    但是我发现,如果目录中出现()括号字符就不行了,当有括号字符的时候在QProcess执行的报错中显示路径被括号截断,此后我把路径用引号引起来没效果:

    ""E:/test_rar_course(xx)/test.bat""

    根据网上搜索到的信息,用^符号对括号进行转义没有截断的报错了,但是命令执行还是没有效果,控制台也没有报错:

    "E:/test_rar_course^(xx^)/test.bat"

    到这里我不知道该怎么样去达到我的效果,唯一的感觉QProcess怎么这么难用,如果有知道的QT大神,烦请告诉一下。我想到用另外一种方式来实现,就是用C++写一个dll实现,然后QT中调用。

    在QT中调用C++创建的dll

    主要代码如下,实际上就是调用system函数,但是如果路径中有圆括号,还是需要用^符号进行转义,否则system执行也有问题:

    void SystemTool::GenerateIndexRar(char * command)
    {
        if(command == NULL) return ;
        system(command);
    }
    

    但是除了圆括号要转义以外,还存在一个很不舒服的问题,就是每次执行都会弹出cmd的黑窗口,执行完成之后,窗口消失,代码改成下面的就好了:

    #include <windows.h>
    void SystemTool::GenerateIndexRar(char * command)
    {
             if(command == NULL) return ; 
             /**
                WinExec 的windows 调用,可以通过参数SW_HIDE隐藏命令行黑窗口
                并且命令的路径是可以带括号的
              */
             WinExec(command,SW_HIDE);
    }
    

    到此完美解决该问题,既不需要对圆括号进行转义,同时也隐藏了黑窗口了。当然前述的test.bat的内容要在程序中动态生成,利用合适的路径替换掉test.bat中的路径。

    最后调用如:SystemTool::GenerateIndexRar("E:/test_rar_course(xx)/test.bat");

  • 相关阅读:
    Android 编译命令 make j8 2>&1 | tee build.log 解释
    Linux时间函数之gettimeofday()函数之使用方法
    转:RSA算法原理说明
    转: 各个密码算法的实现(未验证)
    转:修改Android签名证书keystore的密码、别名alias以及别名密码
    转:Eclipse ADT的Custom debug keystore所需证书规格
    转:如何转换Android打包用jks格式keystore证书为Air用pkcs12格式p12证书
    转: 关于流量控制与令牌桶介绍
    转:sublime2 官方网址
    转:Mac OS X下Sublime Text (V2.0.1)破解
  • 原文地址:https://www.cnblogs.com/wangqiguo/p/4609228.html
Copyright © 2020-2023  润新知