Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QProcess problems, output of process

Tags:

qt

qt4

I am trying to figure out the use of QProcess. I looked at Qt doc with no luck.
http://doc.qt.io/qt-4.8/qprocess.html

EXAMPLES OF PROBLEM.

Example 1: Code bellow works.

    #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, doesn'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();
}

The output of the above code is

hello

F:\Dev_Qt\expControllingExtConsoleApps-build-desktop>

---End, bye----

The problem is that if I try to use ipconfig or 7zip in this fashion via Qprocess and cmd console, I am unable to see any output from ipconfig or 7zip. I don't know if anything is even done, if something is done then why can't I see the output? Code below illustrates.

Example 2: Does not work. Can't use 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 is below, it is missing the ipconfig connection information result. No output from ipconfig is captured at all.

Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.

C:\Program Files\7-Zip> ipconfig

---end----

Should have been more like this (with ipconfig result).

Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\noname>ipconfig

Windows IP Configuration

Ethernet adapter Local Area Connection:

    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>

Obviously the output should should have been a little diff than above but the Connection info which is the output of "ipconfig" should have been captured. In the same way if I try to use 7zip via cmd console... I can not see/capture any output of 7zip. So my question is how can I use command line apps like ipconfig and 7zip via QProcess and cmd console and see the result of the output of these applications?

Example 3: 7zip does not work

#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 below. Does not show anything from 7zip.

Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp.

C:\Program Files\7-Zip>7z.exe

---end----

Output is expected to be along the lines of...

Microsoft Windows XP [Version 5.1.2600] (C) Copyright 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 Copyright (c) 1999-2010 Igor Pavlov 2010-06-20

Usage: 7z [...] <archive_name> [<file_names>...] [<@listfiles...>]

a: Add files to archive
b: Benchmark d: Delete files from archive e: Extract files from archive (without using directory names) l: List contents of archive
t: Test integrity of archive u: Update files to archive x: eXtract files with full paths
-ai[r[-|0]]{@listfile|!wildcard}: Include archives
-ax[r[-|0]]{@listfile|!wildcard}: eXclude archives -bd: Disable percentage indicator
-i[r[-|0]]{@listfile|!wildcard}: Include filenames -m{Parameters}: set compression Method
-o{Directory}: set Output directory -p{Password}: set Password -r[-|0]: Recurse subdirectories -scs{UTF-8 | WIN | DOS}: set charset for list files -sfx[{name}]: Create SFX archive -si[{name}]: read data from stdin -slt: show technical information for l (List) command -so: write data to stdout -ssc[-]: set sensitive case mode -ssw: compress shared files
-t{Type}: Set type of archive -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options -v{Size}[b|k|m|g]: Create volumes -w[{path}]: assign Work directory. Empty path means a temporary directory
-x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames -y: assume Yes on all queries

C:\Program Files\7-Zip>

like image 297
user440297 Avatar asked May 04 '11 23:05

user440297


1 Answers

eI see one big problem. Under windows you issue a commend pressing the Enter key. Writing

cmd.write("command");
cmd.write("\n");


just isn't enough you have to write

cmd.write("command");
cmd.write("\n\r");

Notice the trailing \r. Try this, it should work better, and by better I mean 7zip. I don't know if you'll get ipconfig to work properly.

Good luck and best regards
D

EDIT Here is a working solution:


#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"

Hope that helps. It worked everytime on my machine.

like image 174
Dariusz Scharsig Avatar answered Sep 30 '22 10:09

Dariusz Scharsig