double quotes problems in Qstring - c++

QProcess p;
QString aa = "tasklist /FI 'IMAGENAME x32dbg.exe' /FO LIST | findstr 'PID:'";
aa.replace(0x27,0x22);
qInfo() << aa;
p.start(aa.toStdString().c_str());
p.waitForFinished();
qInfo() << "Output:" << p.readAllStandardOutput() << "Error:" << p.readAllStandardError();
// returned error <ERROR: Invalid argument/option - 'x32dbg.exe\"'.\r\nType \"TASKLIST /?\" for usage.\r\n">
qebug return
{tasklist /FI \"IMAGENAME x32dbg.exe\" /FO LIST | findstr \"PID:\"}
the correct text must be
{tasklist /FI "IMAGENAME eq x32dbg.exe" /FO LIST | findstr "PID:"}
i tried with \"
and add the command line in const char *
all return same result

The problem is you cannot run pipes with QProcess, but only a single process. The workaround would be to pass your command as an argument to cmd.exe:
QProcess p;
p.start("cmd.exe", QStringList() << "/C" << "tasklist /FI \"IMAGENAME x32dbg.exe\" /FO LIST | findstr \"PID:\"");

QDebug's quoting option enabled by default, so use noquote().

bool isRunning(const QString &process) {
QProcess tasklist;
tasklist.start(
"tasklist",
QStringList() << "/NH"
<< "/FO" << "CSV"
<< "/FI" << QString("IMAGENAME eq %1").arg(process));
tasklist.waitForFinished();
QString output = tasklist.readAllStandardOutput();
qInfo() << output ;

Related

Format Powershell output to a minimum

I'm calling Powershell from QProcess
QProcess p;
p.start("powershell.exe", QStringList() << "get-wmiobject win32_networkadapter -filter 'netconnectionstatus = 2' | select netconnectionid");
if (p.waitForFinished())
while(p.canReadLine())
{
auto line = QString::fromStdString(p.readLine().toStdString());
qDebug() << line;
}
From that, on QtCreator output, I see
"\r\n"
"\r\n"
"netconnectionid : Ethernet\r\n"
"\r\n"
"netconnectionid : VirtualBox Host-Only Network\r\n"
"\r\n"
"\r\n"
"\r\n"
I would like to reduce Powershell output to
"Ethernet"
"VirtualBox Host-Only Network"
How to format Powershell output to a minimum?

How to kill a process with QProcess::execute()?

I've some problems with killing a process using taskkill.
My code:
QStringList args;
args << "/F";
args << "/IM testApp.exe";
QProcess::execute("taskkill", args); //Should be 'taskkill /IM testApp.exe /F'
Output (translated from german):
ERROR: Invalid argument - "/IM testApp.exe".
Type "TASKKILL /?" to show the syntax.
"/IM testApp.exe" makes a single arg, but should be two args. You get the command taskkill /F "/IM testApp.exe". The proper invocation is
QStringList args;
args << "/F";
args << "/IM";
args << "testApp.exe";
QProcess::execute("taskkill", args);

CMD cannot read input characters correctly

I tried to use system function to run a cmd command, but I can't get the command output, Because My Windows is Italian When I type / in my system() function to call cmd its getting actually - and not getting / I tried this in my cmd and is receiving this - instead / ,I tried to use chcp 437 for English cmd but , it didn't work
example :
system("net user xxx xxxx /add");
the command is getting :
net user xxx xxxx -add
I just do not want to do this to work in Italian Windows and work for other languages actually, how to solve this problem?
You should never use system(). You are programming in C++. There is no need to use system() since you have access to everything in the, well, system :D. system() was written in C after all.
And there is the security risk: someone could replace system() or the command you are trying to run using system() in your machine and make not-nice-things in your system.
you can change the code page in your code before calling system() using
SetConsoleOutputCP(); that lives in windows.h
1252 is the Latin codepage and should do ok in Italian. Also 65001 is the utf-8 codepage and should also work well
to run your program on the "new" Windows Terminal is also an option since it is Unicode
pass a string to system() and not a literal. this way you can be sure it has what you want, before the call.
it is a good practice to save the codepage in use before change and restore it on exit
A C++ Example
This program
takes an array of commands
const char* command[] =
{
"DIR .\\*.* /O:D",
"NET USER /Add /?"
};
and runs on the console. The commands uses slashes and backslashes and outputs text so you can test a bit more. And you can just edit the array and add new commands to test
You can try alternative codepages. Here I used 65001, the one for Unicode
int originalOCP = GetConsoleOutputCP();
std::cout << "Original CodePage: " << originalOCP << "\n";
SetConsoleOutputCP(65001);
std::cout << "CodePage now is " << GetConsoleOutputCP() << "\n";
The command is written on the console before being passed to system()
std::cout <<
"\n\n\t==> command " <<
i << " is '" <<
command[i] << "'\n\n";
system(command[i]);
The output in Portuguese Windows
Original CodePage: 850
CodePage now is 65001
==> command 0 is 'DIR .\*.* /O:D'
O volume na unidade C não tem nome.
O Número de Série do Volume é 7E52-1BF2
Pasta de C:\Users\toninho\source\repos\ConsoleApplication8\ConsoleApplication8
29/10/2020 10:21 168 ConsoleApplication8.vcxproj.user
29/10/2020 10:38 974 ConsoleApplication8.vcxproj.filters
29/10/2020 10:38 7.199 ConsoleApplication8.vcxproj
29/10/2020 10:59 676 a.cpp
29/10/2020 10:59 <DIR> ..
29/10/2020 10:59 <DIR> .
29/10/2020 10:59 <DIR> Debug
4 arquivo(s) 9.017 bytes
3 pasta(s) 128.838.795.264 bytes disponíveis
==> command 1 is 'NET USER /Add /?'
A sintaxe deste comando é:
NET USER
[nome de usuário [senha | *] [opções]] [/DOMAIN]
nome de usuário {senha | *} /ADD [opções] [/DOMAIN]
nome de usuário [/DELETE] [/DOMAIN]
nome de usuário [/TIMES:{horários | ALL}]
nome de usuário [/ACTIVE: {YES | NO}]
CodePage now is 850
The code
#include <iostream>
#include <windows.h>
int main(int argc, char** argv)
{
const char* command[] =
{
"DIR .\\*.* /O:D",
"NET USER /Add /?"
};
int originalOCP = GetConsoleOutputCP();
std::cout << "Original CodePage: " << originalOCP << "\n";
SetConsoleOutputCP(65001);
std::cout << "CodePage now is " << GetConsoleOutputCP() << "\n";
for (int i = 0; i < sizeof(command) / sizeof(char*); i += 1)
{
std::cout <<
"\n\n\t==> command " <<
i << " is '" <<
command[i] << "'\n\n";
system(command[i]);
};
SetConsoleOutputCP(originalOCP);
std::cout << "CodePage now is " << GetConsoleOutputCP() << "\n";
return 0;
}

Qt - How to execute this command?

I'm trying to accept automatically the host key when connecting to a server using this command
QString cmd = QString("echo y | plink.exe -ssh %1 -i root.ppk -l root exit").arg(strSensorAddress)
When I launch it from cmd.exe in Windows it is working.
I have tried to do it in Qt like this but it doesn't work :
QString cmd = QString("plink.exe -ssh %1 -i root.ppk -l root exit").arg(strSensorAddress);
process1.setStandardOutputProcess(&process2);
process1.start("echo y");
process2.start(cmd);
process2.setProcessChannelMode(QProcess::ForwardedChannels);
And like this :
QStringList arguments;
arguments << "plink.exe" << "-ssh" << strSensorAddress << "-i" << "root.ppk" << "-l" << "root" << "exit";
process1.setStandardOutputProcess(&process2);
process1.start("echo y");
process2.start("cmd.exe", arguments);
process2.setProcessChannelMode(QProcess::ForwardedChannels);

Creating tar.gz-archive from c++ program does not work

I use the following code snippet for creating a tar.gz-archive in an extensive measurement software. After collecting some data in several files I want to archive and compress them for later use.
Everything works fine when I start the program from the shell, all the data is collected and archived correctly.
However the program should start automatically after system start of an embedded Linux system. When it's started via a script in /etc/init.d, no data files are archived/compressed, even though I get the return value 0. Furthermore, the tar.gz-file is created, but it's empty.
Everything else is working fine.
Can anyone please explain, what I have to do in this special case of an automatic start?
int returnValue = -1;
std::string jobString = RESULT_PATH;
jobString += "/";
jobString += lastJobString;
std::string jobFiles = lastJobString + "*.*";
std::string cmd = "tar cvf - ";
cmd += jobFiles;
cmd += " | gzip > ";
cmd += jobString;
cmd += ".tar.gz";
std::cout << "archiving and compressing " << jobFiles << ": " << cmd << std::flush << std::endl;
returnValue = system(cmd.c_str());
std::cout << "archiving and compressing finished. Code: " << returnValue << std::flush << std::endl;
I know that there are several librariers, like libarchive, libtar, etc. which to use is not as lazy as firing a system command, but I would like to know why this does not work for my case.
Furthermore, the version of tar in my busy box does not support option z.
I finally found a solution for my problem and maybe for all the cases when a system command is called by a daemon:
The trick is to create a new shell by the command sh and change the current directory before the tar-function is called:
std::string cmd = "sh -c \" cd ";
cmd += SOURCE_DIR;
cmd+= " && tar cvf - ";
cmd += jobFiles;
cmd += " | gzip > ";
cmd += jobString;
cmd += ".tar.gz";
returnValue = system(cmd.c_str());
Maybe this will help other users heading to the same problem.