I start rsync in QProcess. My process runs fine (in its own terminal) if I use QProcess::startDetached() but nothing happens if I start it with QProcess:start(). The problem seems to be that QProcess can't apparently read messages from rsync and write it to the output window.
I have connect this signal in constructor.
MainWindow::~MainWindow()
{
process = new QProcess(this);
connect( process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadyReadStandardOutput() ) );
}
Later on button clicked I call:
void MainWindow::onButton1Clicked()
{
process->start("rsync -a root#10.0.0.1:/path/ /rsync_folder");
//process->start("ping 10.0.0.01"); // this works for testing and I see output but not the above.
}
When rsync starts, it prints a message and ask for password..none of it is received by my QProcess but the ping message are received..what could be possibly wrong here?
The above grieving line also works directly on windows 7 command line but it just doesn't seem to show any progress in QProcess.
Update
Here is how I displaying the output.
void MainWindow::onReadyReadStandardOutput()
{
qDebug() << process->readAllStandardOutput();
}
http://doc.qt.io/qt-5/qprocess.html#communicating-via-channels
Did you remember to link to and check the standard error channel?
http://doc.qt.io/qt-5/qprocess.html#readAllStandardError
That has fixed it for me in the past for some QProcesses I have started.
Another way I've done it, is to use QProcess::startDetached();
Hope that helps.
My research shows that rsync probably behaves like scp which accordingly this answer doesn't generate output when it is redirected.
Related
I want to write a routine that will automatically change my Machine learning parameters and execute the (Machine learning) code multiple times and save its result into a text file.
The Machine learning code is run from the Ubuntu terminal and its result also are written to the Ubuntu terminal.
I need a way to read data and write data to the Ubuntu terminal from the C++ code.
What I have found so far is the QProcess:
QProcess process;
process.start("gnome-terminal"); //THE TERMINAL IS OPENED INDEED
char w[] = "write";
process.write(w,sizeof(w));
process.waitForFinished();
But nothing is written or read from it
What does working is:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("echo 0534230313");
process2.start("sudo -S poweroff");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
And also this works:
int result = system("echo 0534230313 | sudo -S poweroff"); ///COMMANDS TO TERMINAL
int result2 = system("gnome-terminal"); ///OPEN TERMINAL
But the problem is that I wont be able to read the output result (My Machine learning program can open and write to the terminal by itself)
Use the finished signal to read the process output results
connect( poProcess, static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
[=](int,QProcess::ExitStatus)
{
QByteArray oProcessOutput=
poProcess->readAllStandardOutput();
// Parse the process output.
//
// Mark process for deletion.
emit poProcess->deleteLater();
});
I am starting a QProcess to open cmd.exe.
I want to write to std in to send commands to cmd.exe, and I want to recieve it's output.
QProcess mProcess = new QProcess(this);
mProcess->setReadChannelMode(QProcess::SeparateChannels);
mProcess->start("cmd");
QApplication::processEvents();
QString s(mProcess->readAllStandardOutput());
writeToConsole(s);
This all works just fine. The process starts, I get output. However, I can't now write to the process anymore. I have looked over QProcess documentation and I don't see any way to write to standard in. I've tried mProcess->write(data); but that didn't do anything.
How do I write to standard in to the running process?
You have to use write function only to write in to the standard in.
But the important thing is you have to close the write channel using void QProcess::closeWriteChannel().
Look into below documentation.
http://doc.qt.io/qt-5/qprocess.html#closeWriteChannel
You should wait for operations to finish before moving on to the next action.
QProcess mProcess = new QProcess(this);
mProcess->setReadChannelMode(QProcess::SeparateChannels);
//Start the process
mProcess->start("cmd");
QApplication::processEvents();
mProcess->waitForStarted();
// Read the output
mProcess->waitForReadyRead();
QString output(mProcess->readAllStandardOutput());
mProcess->closeReadChannel();
// Write the data
mProcess->write(output);
mProcess->waitForBytesWritten();
mProcess->closeWriteChannel();
// Wait for finished
mProcess->waitForFinished();
It seems strange to send the output directly back into the program being executed. Alternatively you could connect the void QIODevice::readyRead() signal to a slot where the output can be handled elsewhere.
The mistake I was making here was not putting \n on the end of the multiple commands.
''''
// 1st command
mProcess->write(output1 + "\n");
mProcess->waitForBytesWritten();
// 2nd command
mProcess->write(output1 + "\n");
mProcess->waitForBytesWritten();
// Wait for finished
mProcess->waitForFinished();
mProcess->closeWriteChannel();
''''
I am working in Qt 4.7, and I have a program that needs to use a QProcess to output the result of running a Windows PowerShell command. For the purposes of this question, let's say all that needs to be supported is use of the "-Command" option. Right now I have this:
QString path = "C:/windows/system32/WindowsPowerShell/v1.0/powershell.exe";
QStringList command;
command.append("-Command");
command.append(/*Whatever test command I want to use...*/);
process = new QProcess(); //Note: QProcess *process is a member of this class
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(/*slot to print qprocess errors...*/);
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(/*slot to display PowerShell output...*/);
process->start(path, command);
The slot to print the PowerShell output is simply as follows:
std::cout << "RESULT: " << QString(process->readAllStandardOutput()).toStdString() << std::endl;
This works perfectly with correct PowerShell commands. For example, I tested it with the command "Get-ChildItem C:\", and it printed the correct data. It also works fine if there is a QProcess error. What I need to know how to do is, how can I have it print a PowerShell error message? For example, if I try to use the command "Get-ChildIte" (missing the m at the end) directly in PowerShell I get an error message. But with my code, it just doesn't print anything. I need it to print that error message. If anyone knows of a way this could be done, I'd really appreciate it. Thanks!
Ok, you posted your answer 7 seconds ago. I just wanted to confirm, and give a link to reference for you that may help troubleshoot this in the future.
QProcess Class
Yes, you want the readAllStandardError() function of QProcess.
So, about a minute after I posted this I discovered QProcess's signal readyReadStandardError(), which operates identically to readyReadStandardOutput except that it is emitted when whatever the QProcess is running has an error. I connected this to a slot identical to what I have above but instead printing QString(process->readAllStandardError()).toStdString() and it worked.
Ok, so I am executing a program ./led.sh present in my SBC6845, from my host system using a qt-C++ program. This program basically connects my SBC to my host system. It is the equivalent of "hyperterminal" or "Minicom". I obtained this program (the example code) "uartassistant" inside "qextserialport-1.2rc.zip" from http://code.google.com/p/qextserialport/ .
I came across this link: Running shell command in QT c++ in ubuntu , while searching how to execute a shell command from inside the qt program. I tried and succeeded in executing ./led.sh. Thanks to the link.
I declared
void someaction(); // in the dialog.h
then in dialog.cpp I add this
connect(ui->pushButton, SIGNAL(clicked()), SLOT(someaction()));
and this
void Dialog::someaction()
{
QString command = "sh ./led.sh\r\n"; const char* command2;
command2 = command.toLocal8Bit().data();
port->write(command2);
I was able to do the ledflash in my SBC.
But the problem occurs when I try to stop ./led.sh, I am unable to do so in the uartassistant (bugs, need modification, still working).
But for the time being I am trying to make another pushbutton_1 and put something like "Ctrl+Z" inside and ask ./led.sh to stop.
I came across some other links which I am unable to put due to low reputation points.
I have no idea how to use SIGTERM / kill option[from other links] inside qt app and execute on pushbutton click.
Say if I used kill how would I determine the pidof of multiple such pushbutton actions and assign whom to kill.
Also I would like to add that my SBC has ash [Almquist shell]. So it being low memory clone of Bourne shell, I don't know if it would support normal commands for exiting led.sh.
I have no idea how to use SIGTERM / kill option[from other links]
inside qt app and execute on pushbutton click.
As with so much, Qt gives you an intuitive abstraction that allows you to not have to worry about any of this, namely QProcess. In your case you'd want something like this:
QProcess proc;
proc.start("led.sh");
...
//handle Ctrl-Z event
proc.close();
The first answer here has several other techniques for executing more complicated shell commands.
I have found a temporary solution for my problem. I am yet to try the qprocess action.
In dialog.h I added another function:
void someotheraction();
then in dialog.cpp I did this:
connect(ui->pushButton_2,SIGNAL(clicked()), SLOT(someotheraction()));
and this:
void Dialog::someotheraction()
{
QString command = "\x001a \r\n"; const char* command2; // Ctrl-Z = \x001a
command2 = command.toLocal8Bit().data();
port->write(command2);}
The fifth reply here gave me the idea. I don't know how, but it did the job maybe some one can explain it better.
How can I start a Shell Script using QProcess?
The Shell Script has eight different commands in it, some with arguments others without.
I tried to start the Shell Script with (using Ubuntu 11.10):
QProcess *Prozess = new QProcess();
Prozess->setWorkingDirectory(MainDirectory);
Prozess->start("/bin/sh", QStringList() << "Shell.sh");
But this doesn't work, that means nothing happens. How to make it work?
Code is fine. Problem is at run-time.
Either your program can't run /bin/sh for some reason (test if you can run gedit instead?), or the MainDirectory variable has wrong directory path (debug it), or the Shell.sh does not exist in that directory (capitalization mistakes? What about "./Shell.sh"?), or you don't have enough privileges to run or modify target directory/files (are they owned by you?).
The process you have started is running in background. if you want to see any explicit output from the running script you have to connect to void readyReadStandardOutput() or/and void readyReadStandardError() and read from the process explicitly. For example:
void onReadyRead() {
QByteArray processOutput = Prozess->readAllStandardOutput();
}
This should work:
QProcess::ProcessError Error = myProcess->readAllStandardError();
return Error;
QProcess ().execute ("/bin/sh " + MainDirectory + "/Shell.sh");
will do the job.