QT中QProcess调用命令行的痛苦经历(调用Winrar,设置工作目录,获得输出,注意引号与括号,等等)
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
例子对应的目录结构如下:
上面的命令表示在当前目录下创建压缩包 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");
http://www.cnblogs.com/wangqiguo/p/4609228.html
QT中QProcess调用命令行的痛苦经历(调用Winrar,设置工作目录,获得输出,注意引号与括号,等等)的更多相关文章
- QT中QProcess调用命令行的痛苦经历
在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在QT中通过QProcess类调用命令行的rar.exe来达到效果,但是没想到QProcess类用起来很麻烦,而且达不到效果,折腾了 ...
- Qt_Window@Qt Command Prompt从命令行创建工程
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplicatio ...
- npm中本地安装命令行类型的模块是不注册Path的
http://www.jianshu.com/p/c04dea6e46de 首先有必要解释下什么是命令行(Command Line)类型的模块.npm的模块一共分为三类: 绑定型(Binding):本 ...
- 通过JAVA调用命令行程序
这是我在把数据导入到数据库时遇到问题,总结下来的.包含两个方法,一个方法是读取文件路径下的文件列表,主方法是执行cmd命令,在导入时想得到导入一个文件的时间,涉及到线程阻塞问题,这个问题理解不是很深, ...
- system调用命令行命令而不显示命令行窗口
system调用命令行命令而不显示命令行窗口 通常用system调用命令行命令时都会弹出黑底白字的命令行窗口,下面的代码可以不显示弹出的命令行窗口. 代码如下 #pragma comment( lin ...
- 命令行通过入参调用jar包
命令行通过入参调用jar包 最近因为项目需要,需要实现一个功能,即定时执行服务器上的一个脚本去对数据库的数据进行业务处理,要操作的数据库有很多种,mysql.db2.oracle.sqlserver等 ...
- Vim中常用的命令行
Vim中常用的命令行... ------------------- 一些真正强大的武器总不是那么容易驾驭的,主角总得付出一些努力才能收获到更加强大的力量,对于 Vim 这种上古神器来说更是如此.由于它 ...
- QT uic rcc moc 命令行使用
QT uic rcc moc 命令行使用 PS C:\Users\lsgx> uic.exe --help Usage: C:\Qt\Qt5.5.1\5.5\msvc2012\bin\uic.e ...
- Ruby(或cmd中)输入命令行编译sass
Ruby(或cmd中)输入命令行编译sass步骤如下: 举例: 1.在F盘中新建一个总文件夹,比如test文件夹,其中在该文件夹下面建立html.images.js.sass等文件夹. 2.在sass ...
随机推荐
- 如何让 Qt 的程序使用 Sleep(主线程没有Sleep函数,但线程可用自带的保护函数Sleep)
熟悉的陌生人 Qt 是事件驱动的,所以当你用Qt的时候,几乎时时刻刻和 QEventLoop 打交道.,只是你可能没有意识到: QCoreApplicaton::exec() QApplication ...
- BZOJ1116: [POI2008]CLO
1116: [POI2008]CLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 565 Solved: 303[Submit][Status] ...
- 传智播客8月C/C++基础班开班
秋天已经向我们走来,在这个充满收获的季节里,大家齐聚传智C/C++学院这个大家庭,无论你曾经从事什么工作,都拥有着一颗热爱C/C++的心,为了自己心中的梦想,大家要付出百倍的努力,要做到&quo ...
- 【HDU】I love sneakers!(分组背包)
看了许多的题解,都有题目翻译,很不错,以后我也这样写.直接翻译样例: /*鞋子的数量N[1, 100]; 拥有的金钱M[1, 1w]; 品牌数目[1, 10]*/ /*以下四行是对于每双鞋的描述*/ ...
- python filecmp标准库基础学习
# -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#文件的比较import os,filecmp#作用用于比较系统中的目录和文件#例子 ...
- (转)iOS Wow体验 - 第二章 - iOS用户体验解析(2)
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第二章译文精选的第二部分,其余章节将陆续放出.上一 ...
- web前端代码规范 - HTML代码规范
Bootstrap HTML编码规范 本文转载自w3cschool. 由于bootstrap得到了世界的认可,因此,此规范用于规范html代码有一定的说服力. 交流qq群:164858883.欢迎各位 ...
- atitit。自己定义uml MOF EMF体系eclipse emf 教程o7t
atitit.自己定义uml MOF EMF体系eclipse emf 教程o7t 1. 元对象机制(MOF,Meta-Object Facility)and 结构 1 2. 元模型图.模型图.对 ...
- LDAP禁止匿名访问
LDAP默认是允许用户匿名访问的,如下图:在使用工具连接时,勾选匿名绑定后,不需要输入UserDN和密码就可能连接到LDAP服务器,但是只能进行read及search操作.不能做任何的修改及删除操作. ...
- GridControl 设置焦点单元格
gdvNew.Focus(); //GridControl 控件获取焦点 gdvNew.FocusedRowHandle = _smtReport.Count - 1; //设置焦点行 gdvNew. ...