zoukankan      html  css  js  c++  java
  • QT中QProcess调用命令行的痛苦经历

    源地址:http://www.w2bc.com/Article/47446

    在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类提供的成员函数,其使用的具体代码如下:

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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个项目,那么是不是设置一下工作目录就可以了呢:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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()为启动的进程指定工作目录,运行之后报错,说找不到文件,我猜可能还是工作目录的问题,但是不知道问题在哪里,查了很多资料都无济于事,最终还是放弃了这种尝试,改成了下面的尝试:

    1
    2
    3
    4
    5
    6
    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的内容为如下:

    1
    2
    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执行也有问题:

    1
    2
    3
    4
    5
    void SystemTool::GenerateIndexRar(char * command)
    {
        if(command == NULL) return ;
        system(command);
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #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");

  • 相关阅读:
    HDU 1261 字串数(排列组合)
    Codeforces 488C Fight the Monster
    HDU 1237 简单计算器
    POJ 2240 Arbitrage
    POJ 3660 Cow Contest
    POJ 1052 MPI Maelstrom
    POJ 3259 Wormholes
    POJ 3268 Silver Cow Party
    Codesforces 485D Maximum Value
    POJ 2253 Frogger(最短路)
  • 原文地址:https://www.cnblogs.com/lanye/p/5363597.html
Copyright © 2011-2022 走看看