我试图找出QProcess的用法。我没有运气地看着Qt doc http://doc.qt.io/qt-4.8/qprocess.html
问题示例。
示例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();
}
上述代码的输出是
您好
F:\Dev_Qt\expControllingExtConsoleApps-build-desktop> ---End, bye----
问题是,如果我尝试通过Qprocess和cmd控制台以这种方式使用ipconfig或7zip,我将无法看到ipconfig或7zip的任何输出。我不知道是否有任何事情已经完成,如果有什么事情已经完成,那么为什么我看不到输出?代码如下:
示例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();
}
输出如下,缺少ipconfig连接信息结果。根本没有捕获ipconfig的输出。
Microsoft Windows XP [版本 5.1.2600](C)版权所有1985-2001 Microsoft Corp.
C:\ Program Files \ 7-Zip&gt; IPCONFIG
--- ----结束
应该更像这样(使用ipconfig结果)。
Microsoft Windows XP [版本 5.1.2600](C)版权所有1985-2001 Microsoft Corp.
C:\ Documents and 设置\ NONAME&GT; IPCONFIG
Windows IP配置
以太网适配器本地区域 连接:
Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 192.172.148.135 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 192.172.148.177
C:\ Documents and Settings \ noname&gt;
显然输出应该比上面有点差异,但连接信息应该是“ipconfig”的输出应该被捕获。以同样的方式,如果我尝试通过cmd控制台使用7zip ...我无法看到/捕获7zip的任何输出。所以我的问题是如何通过QProcess和cmd控制台使用命令行应用程序,如ipconfig和7zip,并查看这些应用程序的输出结果?
示例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();
}
下面是输出。没有显示7zip的任何内容。
Microsoft Windows XP [版本 5.1.2600](C)版权所有1985-2001 Microsoft Corp.
C:\ Program Files \ 7-Zip&gt; 7z.exe
--- ----结束
预计产出将符合......
Microsoft Windows XP [版本 5.1.2600](C)版权所有1985-2001 Microsoft Corp.
C:\ Documents and Settings \ noname&gt; cd C:\ Program Files \ 7-Zip
C:\ Program Files \ 7-Zip&gt; 7z.exe
7-Zip 9.15 beta版权所有(c) 1999-2010 Igor Pavlov 2010-06-20
用法:7z [...] [...] 并[d @listfiles ...&GT;]
a:将文件添加到存档中 b:基准测试d:从中删除文件 存档e:从中提取文件 存档(不使用目录 名称)l:列出档案的内容
t:测试档案的完整性你: 更新文件以存档x:eXtract 完整路径的文件
-ai [r [ - | 0]] {@ listfile |!wildcard}:包含档案
-ax [r [ - | 0]] {@ listfile |!wildcard}:eXclude archives -bd:Disable 百分比指标
-i [r [ - | 0]] {@ listfile |!wildcard}:包含文件名-m {Parameters}: 设定压缩方法
-o {Directory}:set输出目录-p {Password}:set Password -r [ - | 0]:Recurse子目录-scs {UTF-8 | 赢| DOS}:为列表文件设置charset -sfx [{name}]:创建SFX存档-si [{name}]:从stdin -slt读取数据:显示l(List)命令的技术信息-so:将数据写入 stdout -ssc [ - ]:设置敏感案例 mode -ssw:压缩共享文件
-t {Type}:设置档案类型-u [ - ] [p#] [q#] [r#] [x#] [y#] [z#] [!newArchiveName]: 更新选项-v {Size} [b | k | m | g]: 创建卷-w [{path}]:assign 工作目录。空路径意味着 临时目录
-x [r [ - | 0]]] {@ listfile |!wildcard}:eXclude文件名-y:假设是 所有查询C:\ Program Files \ 7-Zip&gt;
答案 0 :(得分:4)
cmd.write("command");
cmd.write("\n");
你还不够写
cmd.write("command");
cmd.write("\n\r");
注意尾随\ r \ n。尝试这个,它应该更好,并且更好,我的意思是7zip。我不知道你是否会让ipconfig正常工作。
祝你好运和最好的问候 dEDIT 这是一个有效的解决方案:
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QString>
#include <QtCore/QTextStream>
// Not clean, but fast
QProcess *g_process = NULL;
// Needed as a signal catcher
class ProcOut : public QObject
{
Q_OBJECT
public:
ProcOut (QObject *parent = NULL);
virtual ~ProcOut() {};
public slots:
void readyRead();
void finished();
};
ProcOut::ProcOut (QObject *parent /* = NULL */):
QObject(parent)
{}
void
ProcOut::readyRead()
{
if (!g_process)
return;
QTextStream out(stdout);
out << g_process->readAllStandardOutput() << endl;
}
void
ProcOut::finished()
{
QCoreApplication::exit (0);
}
int main (int argc, char **argv)
{
QCoreApplication *app = new QCoreApplication (argc, argv);
ProcOut *procOut = new ProcOut();
g_process = new QProcess();
QObject::connect (g_process, SIGNAL(readyReadStandardOutput()),
procOut, SLOT(readyRead()));
QObject::connect (g_process, SIGNAL(finished (int, QProcess::ExitStatus)),
procOut, SLOT(finished()));
g_process->start (QLatin1String ("cmd"));
g_process->waitForStarted();
g_process->write ("ipconfig\n\r");
// Or cmd won't quit
g_process->write ("exit\n\r");
int result = app->exec();
// Allright, process finished.
delete procOut;
procOut = NULL;
delete g_process;
g_process = NULL;
delete app;
app = NULL;
// Lets us see the results
system ("pause");
return result;
}
#include "main.moc"
希望有所帮助。它每次都在我的机器上工作。
答案 1 :(得分:4)
尽管Dariusz Scharsig已经提供了解决问题的方法,但我想指出我认为可以使用信号槽机制解决的实际问题。
问题1。您的while循环中的条件基于bool QProcess::atEnd () const
,符合QProcess Documentation州:
从QIODevice :: atEnd()重新实现。
如果进程是,则返回true 没有运行,没有更多的数据可供阅读;除此以外 返回false。
但如果您查看QIODevice::atEnd()的文档,则说明:
如果当前读写位置在末尾,则返回true 该设备(即没有更多的数据可供阅读 设备);否则返回false。
对于某些设备,atEnd()可以返回 即使有更多数据需要阅读也是如此。仅限这种特殊情况 适用于直接响应您生成数据的设备 调用read()(例如,Unix和Mac OS X上的/ dev或/ proc文件,或者 所有平台上的控制台输入/ stdin )。
解决方案1。更改while循环条件以检查流程的状态:while(cmd2.state()!=QProcess::NotRunning){
。
问题2。您在循环之外使用cmd2.waitForReadyRead();
。也许有些数据现在可供阅读,当你读完之后,还有更多数据可用:
ipconfig\n
atEnd()
也是如此。 解决方案2. 将waitForReadyRead()
放入循环中。
结果2。 waitForReadyRead()
会告诉您何时有可用的数据,哪些可能不止一行,因此您也应该将cmd2.ReadLine()
更改为{{ 1}}。
问题3。如[{3}}
中所述关闭读写输入的程序需要关闭写通道 数据直到频道关闭。
解决方案3。完成输入
后,以下选项之一应该有效cmd2.ReadAll()
cmd2.write("exit\n");
工作代码:
cmd2.closeWriteChannel();
我写这个答案只是为了解释我理解你的问题并找到解决方案的方式,但我想强调优先解决方案是使用QProcess::closeWriteChannel()。