我想弄清楚QProcess的用途 . 我没有运气地看着Qt doc .
http://doc.qt.io/qt-4.8/qprocess.html
EXAMPLES OF PROBLEM.
Example 1: 代码bellow工作 .
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QProcess cmd;
cmd.start("cmd");
if (!cmd.waitForStarted()) {
return false;
}
cmd.waitForReadyRead();
QByteArray result = cmd.readAll();
//qout << result.data() << endl; //console junk captured, don't show.
//My test command
cmd.write("echo hello");
cmd.write("\n");
//Capture my result
cmd.waitForReadyRead();
//This is my command shown by cmd, I don't show it, capture & discard it.
result = cmd.readLine();
//Read result of my command ("hello") and the rest of output like cur dir.
result = cmd.readAll();
qout << result.data();
qout << "\n\n---End, bye----" << endl;
return a.exec();
}
上面代码的 output 是
你好F:\ Dev_Qt \ expControllingExtConsoleApps-build-desktop>
---结束,再见----
问题是,如果我尝试通过Qprocess和cmd控制台以这种方式使用ipconfig或7zip,我将无法看到ipconfig或7zip的任何输出 . 我不知道是否有任何事情已经完成,如果有什么事情已经完成,那么为什么我看不到输出?代码如下所示 .
Example 2: 不起作用 . 无法使用ipconfig .
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QString>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QProcess cmd2;
cmd2.setWorkingDirectory("C:/Program Files/7-Zip"); //not needed in this example.
cmd2.setReadChannel(QProcess::StandardOutput);
cmd2.setProcessChannelMode(QProcess::MergedChannels);
cmd2.start("cmd");
if (!cmd2.waitForStarted())
{
qout << "Error: Could not start!" << endl;
return false;
}
cmd2.waitForReadyRead();
QByteArray result = cmd2.readAll();
qout << result.data() << endl; //Console version info, etc.
//My command
cmd2.write("ipconfig");
cmd2.write("\n");
//Capture output of ipconfig command
//DOES NOT WORK!!
cmd2.waitForReadyRead();
while (! cmd2.atEnd())
{
result = cmd2.readLine();
qout << result;
result.clear();
}
qout << endl;
qout << "\n\n---end----" << endl;
return a.exec();
}
Output 如下,它缺少ipconfig连接信息结果 . 根本没有捕获ipconfig的输出 .
Microsoft Windows XP [版本5.1.2600](C)版权所有1985-2001 Microsoft Corp. C:\ Program Files \ 7-Zip> ipconfig --- end ----
应该更像这样(使用ipconfig结果) .
Microsoft Windows XP [版本5.1.2600](C)版权所有1985-2001 Microsoft Corp. C:\ Documents and Settings \ noname> ipconfig Windows IP配置以太网适配器本地连接:特定于连接的DNS后缀 . :
IP地址 . . . . . . . . . . . . :192.172.148.135
子网掩码 . . . . . . . . . . . :255.255.255.0
默认网关 . . . . . . . . . :192.172.148.177
C:\ Documents and Settings \ noname>
显然输出应该比上面有点差异,但连接信息应该是“ipconfig”的输出应该被捕获 . 以同样的方式,如果我尝试通过cmd控制台使用7zip ...我无法看到/捕获7zip的任何输出 . 所以我的问题是如何通过QProcess和cmd控制台使用命令行应用程序,如ipconfig和7zip,并查看这些应用程序的输出结果?
Example 3: 7zip不起作用
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include <QByteArray>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream qout(stdout);
QProcess cmd2;
cmd2.setWorkingDirectory("C:/Program Files/7-Zip");
cmd2.setReadChannel(QProcess::StandardOutput);
cmd2.setProcessChannelMode(QProcess::MergedChannels);
cmd2.start("cmd");
if (!cmd2.waitForStarted()) {
return false;
}
//My Command
cmd2.write("7z.exe");
cmd2.write("\n");
//Capture output of ipconfig command
cmd2.waitForReadyRead();
QByteArray result;
while (! cmd2.atEnd()) {
result = cmd2.readLine();
qout << result;
result.clear();
}
qout << endl;
qout << "\n\n---end----" << endl;
return a.exec();
}
Output 贝娄 . 7zip没有显示任何内容 .
Microsoft Windows XP [版本5.1.2600](C)版权所有1985-2001 Microsoft Corp. C:\ Program Files \ 7-Zip> 7z.exe --- end ----
预计产量将符合......
Microsoft Windows XP [版本5.1.2600](C)版权所有1985-2001 Microsoft Corp. C:\ Documents and Settings \ noname> cd C:\ Program Files \ 7-Zip C:\ Program Files \ 7-Zip> 7z .exe 7-Zip 9.15 beta版权所有(c)1999-2010 Igor Pavlov 2010-06-20用法:7z [...] [...] [<@listfiles ...>] a:将文件添加到存档b :基准测试d:从存档中删除文件e:从存档中提取文件(不使用目录名称)l:列出存档的内容t:测试存档的完整性u:更新文件以存档x:使用完整路径的eXtract文件-ai [r [ - | 0]] {@ listfile |!wildcard}:包含档案-ax [r [ - | 0]] {@ listfile |!wildcard}:eXclude archives -bd:禁用百分比指标-i [r [ - | 0] ] {@ listfile |!wildcard}:包含文件名-m {参数}:设置压缩方法-o {目录}:设置输出目录-p {密码}:设置密码-r [ - | 0]:递归子目录-scs { UTF-8 |赢| DOS}:为列表文件设置字符集-sfx []:创建SFX存档-si []:从stdin -slt读取数据:显示l(List)命令的技术信息-so:将数据写入stdout -ssc [ - ]:设置敏感案例模式-ssw:压缩共享文件-t :设置档案类型-u [ - ] [p#] [q#] [r#] [x#] [y#] [z#] [!newArchiveName]:更新选项-v [b | k | m | g]:创建卷-w []:assign工作目录 . 空路径表示临时目录-x [r [ - | 0]]] {@ listfile |!wildcard}:eXclude filenames -y:假设所有查询都为是C:\ Program Files \ 7-Zip>
2 回答
我看到一个大问题 . 在Windows下,按Enter键发出推荐信 . 写作
只是你不得不写
注意尾随\ r \ n . 尝试这个,它应该更好,并且更好,我的意思是7zip . 我不知道你是否会让ipconfig正常工作 .
祝你好运和最好的问候
d
编辑这是一个有效的解决方案:
希望有所帮助 . 它每次都在我的机器上工作 .
尽管Dariusz Scharsig已经提供了解决问题的方法,但我想指出我认为可以使用信号槽机制解决的实际问题 .
Problem 1. while循环中的条件基于
bool QProcess::atEnd () const
,根据QProcess Documentation状态:但如果你查看QIODevice::atEnd()的文档,它会说:
Solution 1. 更改while循环条件以检查进程的状态:
while(cmd2.state()!=QProcess::NotRunning){
.Problem 2. 您在循环外使用
cmd2.waitForReadyRead();
. 也许有些数据现在已经可以阅读了,当你读完之后,还有一些数据可用:你读了刚写的命令:
ipconfig\n
ipconfig需要一些时间来启动并将文本发送到控制台 . 但到那时你已经退出循环,因为即使你的进程仍在运行,
atEnd()
也是如此 .Solution 2. 将
waitForReadyRead()
放入循环中 .Consequence 2.
waitForReadyRead()
将告诉您何时有可用数据,哪些可能是多行,因此您也应该将cmd2.ReadLine()
更改为cmd2.ReadAll()
.Problem 3. 如QProcess::closeWriteChannel()中所述
Solution 3. 完成输入输入后,以下选项之一应该有效
结束流程:
cmd2.write("exit\n");
关闭Writechannel:
cmd2.closeWriteChannel();
工作代码:
我写这个答案只是为了解释我理解你的问题的方式并找到了解决方案,但我想强调的是 Preferable Solution 是使用Signal/Slot Mechanism as presented by Dariusz .