Error in processing command in QProcess - qt

I am trying to execute following command and trying to get the output however I am getting output as null.
QProcess process;
process.start("cmd /c \"ipconfig\"");
process.waitForFinished(-1);
QByteArray out = process.readAll();
QString testStr = QString::fromUtf8(out);
Can someone please tell me where am I doing wrong?

process.start("C:\\Windows\\System32\\cmd.exe /c \"ipconfig\"");

Related

arp command with grep argument in QProcess [duplicate]

I'm using Qt and bash over it, need to execute something like:
bash: cat file | grep string
in Qt:
QString cmd = "cat file | grep string";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();
The problem is in pipe ("|"), and process returs nothing. If there is no ("|"), like
"cat file"
everything is ok.
I tried smth. like
"cat file \\| grep string",
"cat file \| grep string"
but result is the same. If I copy the command and run it in bash everything is ok.
QString::toAscii().data()
and other transforms also have bad result.
The problem is you cannot run a system command with QProcess, but only a single process. So the workaround will be to pass your command as an argument to bash:
process.start("bash", QStringList() << "-c" << "cat file | grep string");
The quick and dirty hack would be this:
QString cmd = "/bin/sh -c \"cat file | grep string\"";
You could also avoid the escaping in there with C++11's R"", but the point is that do not use bash in there because that will make it only work with bash. It will not work on embedded with busybox without bash, just ash, or any other common desktop shell.
/bin/sh is usually a symlink to the shell interpreter used, so that will eventually work.
BUT!
I think you are thinking a bit too low-level when using a high-level C++/OOP framework such as Qt. I would not recommend to invoke the commands in the low-level way when you run it from bash. There is some dedicated high-level convenience API for this use case.
Based on the official documentation, QProcess is supposed to work for pipe'd commands:
void QProcess::setStandardOutputProcess(QProcess * destination)
Pipes the standard output stream of this process to the destination process' standard input.
In other words, the command1 | command2 shell command command can be achieved in the following way:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("cat file");
process2.start("grep string");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
// Wait for it to start
if(!process1.waitForStarted())
return 0;
bool retval = false;
QByteArray buffer;
while ((retval = process2.waitForFinished()));
buffer.append(process2.readAll());
if (!retval) {
qDebug() << "Process 2 error:" << process2.errorString();
return 1;
}
qDebug() << "Buffer data" << buffer;
This is not the main point, but a useful suggestion: do not use QString::toAscii(). That API has been deprecated in Qt 5.
The problem is that when you call process->start(cmd), the commands following the the call to cat are all interpreted as arguments to cat, so the pipe is not doing what you're expecting. If you start with a call to bash with a parameter of a string, you should get what you want: -
QString cmd = "bash -c \"cat file | grep string\"";
Alternatively, you could just call "cat file" and do the search on the returned QString when you read the output from the QProcess
how about this :
QString program = "program";
QStringList arguments;
download = new QProcess(this);
download->start(program, arguments);
If Google brought you here and you are using PyQt5 or PySide2
process1 = QProcess()
process2 = QProcess()
process1.setStandardOutputProcess(process2)
process1.start(cat, [file])
process2.start(grep, [string])

Running Autoit from command line and see errors/results

I am trying to run some autoit.au3 script from command line and see results there. I have put some ConsoleWrite inside script and also Exit(1) but after I run script nothing is shown in console. It just stop script on Exit and ConsoleWrite is not displayed.
I have use command:
"C:...(path to my AutoIt3.exe)" /ErrorStdOut "path_to_my_script.au3"'
Also I have tried to run script.exe with this same command but with similar (no) result. I would like to see output in console and/or custom error messages when script fail (I don't know if that is possible).
AutoIt3.exe is a GUI program. So the STD streams of a GUI program are not printed at a console by default.
The /ErrorStdOut argument redirects errors messages to Console instead of a Msgbox.
This argument does not enable print at the Console.
Command Prompt:
To print at a Command Prompt, you could pipe to more, i.e.
"C:...(path to my AutoIt3.exe)" /ErrorStdOut "path_to_my_script.au3" 2>&1|more
more reads from the Stdin stream and prints to Console.
I intentionly added 2>&1 so the Stderr stream is merged with
Stdout so you get the merged streams printed.
If you do not want the errors, then you can redirect the Stderr stream to nul i.e.
replace 2>&1 with 2>nul.
If you used a for loop at a Command Prompt, it would be i.e.
for /f "delims=" %A in ('"C:...(path to my AutoIt3.exe)" /ErrorStdOut test1.au3') do echo %A
If you use the for loop in batch-file, use %%A instead of %A. To also capture the Stderr, insert 2^>&1 into the for command or to ignore, insert 2^>nulinto the for command i.e.
for /f "delims=" %A in ('2^>nul "C:...(path to my AutoIt3.exe)" /ErrorStdOut test1.au3') do echo %A
The previous methods will not get the Exitcode.
AutoIt code:
An AutoIt script can get the Stdout and the Exitcode.
#pragma compile(Out, 'consoleau3.exe')
#pragma compile(Console, True)
$sAutoit = 'C:...(path to my AutoIt3.exe)'
$iPid = Run('"' & $sAutoit & '" /ErrorStdout ' & $CMDLINERAW, '', #SW_SHOW, 2) ; 2 = Get Stdout stream.
If #error Then Exit
; Open process handle.
$hPid = _ProcessOpenHandle($iPid)
; Get Stdout stream and then print to Console.
$sStdout = ''
Do
Sleep(10)
If $sStdout Then ConsoleWrite($sStdout & #CRLF)
$sStdout = StdoutRead($iPid)
Until #error
; Require process to be closed before calling _ProcessGetExitCode()
ProcessWaitClose($iPid)
; Get exitcode of process.
$iExitcode = _ProcessGetExitCode($hPid)
; Close process handle.
_ProcessCloseHandle($hPid)
Exit $iExitcode
Func _ProcessOpenHandle($iPID)
; Get the process handle of the process to query\n Return: Success Handle as array. Failure 0
Local Const $PROCESS_QUERY_INFORMATION = 0x400
Local $hPID = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', $PROCESS_QUERY_INFORMATION, 'int', 0, 'int', $iPID)
If #error Then Return SetError(#error, #extended, 0)
Return $hPID[0]
EndFunc
Func _ProcessGetExitcode($hPID)
; Get exitcode of the closed process\n Return: Success Exitcode as integer. Failure 0
Local $vPlaceholder
$hPID = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $hPID, 'int*', $vPlaceholder)
If #error Then Return SetError(#error, #extended, 0)
Return $hPID[2]
EndFunc
Func _ProcessCloseHandle($hPID)
; Close the handle of a process\n Return: Success 1. Failure 0
DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $hPID)
If #error Then Return SetError(#error, #extended, 0)
Return 1
EndFunc
Correct the path to AutoIt.exe in the code.
Compile to AutoIt code to executable. It will be a Console program
and will be named consoleau3.exe as to the #pragma compile directives.
Usage:
consoleau3 "path_to_my_script.au3"
Script arguments can be added i.e.
consoleau3 "path_to_my_script.au3" arg1 arg2 arg3 ...

SCP always returns the same error code

I have a problem copying files with scp. I use Qt and copy my files with scp using QProcess. And when something bad happens I always get exitCode=1. It always returns 1. I tried copying files with a terminal. The first time I got the error "Permission denied" and the exit code was 1. Then I unplugged my Ethernet cable and got the error "Network is unreachable". And the return code was still 1. It confuses me very much cause in my application I have to distinct these types of errors.
Any help is appreciated. Thank you so much!
See this code as a working example:
bool Utility::untarScript(QString filename, QString& statusMessages)
{
// Untar tar-bzip2 file, only extract script to temp-folder
QProcess tar;
QStringList arguments;
arguments << "-xvjf";
arguments << filename;
arguments << "-C";
arguments << QDir::tempPath();
arguments << "--strip-components=1";
arguments << "--wildcards";
arguments << "*/folder.*";
// tar -xjf $file -C $tmpDir --strip-components=1 --wildcards
tar.start("tar", arguments);
// Wait for tar to finish
if (tar.waitForFinished(10000) == true)
{
if (tar.exitCode() == 0)
{
statusMessages.append(tar.readAllStandardError());
return true;
}
}
statusMessages.append(tar.readAllStandardError());
statusMessages.append(tar.readAllStandardOutput());
statusMessages.append(QString("Exitcode = %1\n").arg(tar.exitCode()));
return false;
}
It gathers all available process output for you to analyse. Especially look at readAllStandardError().

How to use QProcess?

I want to open a project of QGIS from a QProcess object.
If I am under console I must type
qgis --project /path/of/my/qgis/project/nameofproject.qgs
Then, I do the next:
QString app="qgis";
QStringList arguments;
arguments.append ("--project /path/of/my/qgis/project/nameofproject.qgs");
And then I call it in this way:
proceso->start(app,arguments);
But I have this error in the call:
Cannot find /home/david/Programacion/Qt/SQL/Sql2/build-prueba2-Desktop_Qt_5_3_GCC_64bit-Debug/--project /home/david/GIS/CRCC.qgs
where:
/home/david/Programacion/Qt/SQL/Sql2/build-prueba2-Desktop_Qt_5_3_GCC_64bit-Debug/ is the path of my Qt application and
--project /home/david/GIS/CRCC.qgs is the path I set in the arguments QStringList
I don know how must I set the QProcess object for avoid the path of my app.
Thank you
I would try this in the following ways. With a single command:
const QString command( "qgis --project /path/of/my/qgis/project/nameofproject.qgs" );
QProcess process;
process.start( command );
Or with arguments:
const QString program( "qgis" );
QStringList arguments;
arguments << "--project";
arguments << "/path/of/my/qgis/project/nameofproject.qgs";
QProcess process;
process.start( program, arguments );

Qt - Wait for Qprocess to finish

I'm using CMD by QProcess but I have a problem.
My code:
QProcess process;
process.start("cmd.exe");
process.write ("del f:\\b.txt\n\r");
process.waitForFinished();
process.close();
When I don't pass an argument for waitForFinished() it waits for 30 secs. I want to terminate QProcess after CMD command is executed! Not much and not less!
You need to terminate the cmd.exe by sending exit command, otherwise it will wait for commands
Here is my suggestion:
QProcess process;
process.start("cmd.exe");
process.write ("del f:\\b.txt\n\r");
process.write ("exit\n\r");
process.waitForFinished();
process.close();
The process you're starting is cmd.exe which, by itself will, not terminate. If you call cmd with arguments, you should achieve what you want: -
QProcess process;
process.start("cmd.exe \"del f:\\b.txt"\"");
process.waitForFinished();
process.close();
Note that the arguments are escaped in quotes.
Alternatively, you could call the del process, without cmd: -
QProcess process;
process.start("del \"f:\\b.txt"\"");
process.waitForFinished();
process.close();
Finally, if you just want to delete a file, you could use the QFile::remove function.
QFile file("f:\\b.txt");
if(file.remove())
qDebug() << "File removed successfully";

Resources