QProcess not working on win32 systems? - c++

The process method is not working if I pass the user home directory programmatically in windows XP and windows 32 bit systems
The below code works fine:
QProcess process;
process.execute("C:/DOCUME~1/pjo/myprok/tmp/APP.exe");
Not working Code:
Here I am getting the path of the APP.exe using QDir::homePath
process.execute("C:/Documents and Settings/pjo/myprok/tmp/APP.exe");
The errorString returns "UnKnown error"
I tried with start method also which never works:
B Not working Code:
process.start("C:/Documents and Settings/pjo/myprok/tmp/APP.exe");
Error: Path Not found
process.start("C:/DOCUME~1/pjo/myprok/tmp/APP.exe");
Error : Unknown error

execute() is a static function, so it should be called like this:
QProcess::execute("C:/Documents and Settings/pjo/myprok/tmp/APP.exe");
You are saying that you get the home directory programmatically, but the code you show does not do that. Maybe you are creating the path like this:
QProcess::execute(QDir::homePath() + "APP.exe");
and then the path will miss / between directory and filename like this:
"C:/Documents and Settings/pjo/myprok/tmpAPP.exe"

Your issue is probably due quoting issues caused by the spaces in the path (C:\Documents and Settings...).
Note that there are two overloads for start():
void start ( const QString & program, OpenMode mode = ReadWrite )
void start ( const QString & program, const QStringList & arguments, OpenMode mode = ReadWrite )
You are using the first, which takes the executable path and all args in one string, and expects it to be quoted correctly. Without quoting, "c:\documents" is interpreted as the executable and "and" "Settings..." etc. as the arguments.
The second version takes the arguments separately, and will interpret the executable path correctly, without any quoting needed. Thus, the easiest way is to use
process.start("C:/Documents and Settings/pjo/myprok/tmp/APP.exe", QStringList());
This ensure the second version to be used, and should save you from all quoting issues.
I suggest to always use that overload.
The same applies to execute(), which is, as already said, a static method, so the error codes of the QProcess object won't be set.

Related

What is the correct way to execute a CMD command with QProcess to get the output as QString?

I'm new using QT, I need to execute a CMD command on windows and get the output of this command as a string to later process and get specific data. The following code works well (it seems to work well). The only problem is that I get the following warning: "start is deprecated", I think this warning message is because the start method needs an arguments list as parameter.
QString command = "tasklist /FI \"IMAGENAME eq notepad.exe\"";
QProcess *executeCommand = new QProcess();
executeCommand->start(command);
executeCommand->waitForFinished(-1);
QString output = executeCommand->readAllStandardOutput();
executeCommand->terminate();
qDebug() << commandOutput;
how can I remove this warning message?
Also I found in the web that I can use system() to execute a CMD command, but I'm not able to catch the output as string.
Another question: which of the above options is better to achieve what I'm trying to do, the QProcess or System (if is possible to get the output as QString)?
Thanks in advance!
There is an answer read QProcess output to string recommending static method QProcess::readAllStandardOutput() returning QByteArray. Then just instantiate QString from QByteArray implicitly.
If you are working on Qt application, it is better to stay inside Qt API to keep the code more or less portable.

Calls to system() do not behave the same way as in command prompt (cmd)

I need to cut&paste a folder into another folder through code in C++. But some directory names are problematic, such as the ones which have japanese symbols. However, the same commands introduced through cmd all work fine.
system("move dirName dirName2"); //work
system("move ディレクトリ dirName2"); //does not work (system cannot find the specified file)
system("move ディレクトリ.txt dirName2"); //work
Funny enough, if the item which has the japanese symbols is a file and not a folder, the operation works fine even using calls to system().
I have no idea why the second call to system() does not work or how to solve it.
PS: I'm working with Windows7.
"move dirName dirName2", it is a const char* type, while the Japanese chars are not ASII chars, you should use the unicode API here, try:
_wsystem(L"move ディレクトリ dirName2")
It is likely that you need to use _wsystem instead to accomodate the wide characters. See the relevant MSDN pagefor details, but the syntax of the call is the same.

QProcess issue in executing a exe with arguments

I have a issue in setting the QProcess to run executable with the arguments. The Qt code for the same is as below,
QString program = "C:\Setup.exe";
QStringList arguments;
arguments << "-uninstall";
QProcess::startDetached(program, arguments);
The output of this snippet is to uninstall some program. But it is not happening. Am i doing any mistake?
But if I go to cmd prompt and execute the same thing like.,
c:/> "C:/Setup.exe" -uninstall
This works perfectly.
There are at least two options to solve your issue.
Use '/' for directory separators as per documentation:
If you always use "/", Qt will translate your paths to conform to the underlying operating system.
Escape the backslash whenever working with file paths as string as per an example from the documentation:
env.insert("TMPDIR", "C:\\MyApp\\temp"); // Add an environment variable
env.insert("PATH", env.value("Path") + ";C:\\Bin");
Therefore, you should be writing something like this:
QString program = "C:/Setup.exe";
QStringList arguments;
arguments << "-uninstall";
QProcess::startDetached(program, arguments);
or this:
QString program = "C:\\Setup.exe";
QStringList arguments;
arguments << "-uninstall";
QProcess::startDetached(program, arguments);
In general, when facing such issues, you could always print out the error string to get more information by using the following syntax:
qDebug() << myProcess.errorString();
This, for sure, needs an instance, however.

Diagnosing QDir::rmdir failure

I’m using the following code to delete an empty folder on Linux:
bool removeFolder (const QString& path)
{
QDir dir(path);
assert(dir.exists());
return dir.rmdir(".");
}
For some reason it sometimes returns false (for specific folders, but those folders don’t seem to be wrong in any way). If I subsequently use ::rmdir from <unistd.h> to remove the same folder, it succeeds.
How can I tell why QDir::rmdir is failing?
This never happened on Windows so far, QDir::rmdir just works.
Confirming: works on windown, fails on linux.
Reading the "rmdir" doc in <unistd>, here https://pubs.opengroup.org/onlinepubs/007904875/functions/rmdir.html, it says there that "If the path argument refers to a path whose final component is either dot or dot-dot, rmdir() shall fail." So what's probably happening is that QDir::rmdir() is calling the unistd rmdir() function in linux, and this one fails with ".".
I tried to just use the full absolute path ( QDir::rmdir(absolutePath) ) and it worked; however, i see basically no point in using QDir::rmdir() over unistd's rmdir(), so i''ll stick w/ the unistd rmdir() from now on.
note: QDir::removeRecursively() is a different story: it seems to work okay, and it's way more convenient than going through opendir() and then successive readdir()'s (or the nftw(...FTW_DEPTH...) thingie).
I had the same problem but on Windows, I could not delete an empty directory with QDir().rmdir(path);. This happened on some older hard drive so may be the ancient file system was to blame. But I found a hack:
QFile(path).setPermissions(QFile::WriteOther); // this works even for dirs
bool success = QDir().rmdir(path);
Of course, you should revert the permissions back to original values if the deletion was unsuccessful anyway, but that's a different story.
Try to use this one:
dir.rmdir(dir.absolutePath())

Problems passing source command to bash from c++ application

I am developing an application for work that allows the users to quickly set environment variables on a terminal basis. By setting the path in each terminal we ensure files with the same name in different directories aren't causing application testing to be problematic. I am Using Qt to build the program which is c++ based and all the datatypes are foundationally the same.
I am using the following code to invoke commands in the terminal from which the application launches from using system(). I can run commands into the bash just fine with code; however, I run into a problem when I attempt to use a command with arguments. This is probably why source doesn't seem to work right as the source command is followed by the filename. It would appear that I drop the argument appended after the bash command.
My Code:
void assignTerminalToPath(QString path)
{
QString data = "";
QString currentUsersHomeDirectory = QDir::homePath();
QString tmpScriptLocation = currentUsersHomeDirectory;
QByteArray ba;
tmpScriptLocation += "/.tmpSourceFile";
QFile tmpSourceFile(tmpScriptLocation);
if(tmpSourceFile.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream output(&tmpSourceFile);
data.append("export PATH=.:");
data.append(path);
data.append(":$PATH");
output << QString("#!/bin/bash\n");
output << data;
tmpSourceFile.close();
}
data.clear();
data.append("/bin/bash -c source ");
data.append(tmpScriptLocation);
ba = data.toLatin1();
const char *cStr = ba.data();
system(cStr);
}
Perhaps I'm not referencing bash correctly and I need something outside of -c?
Reference Execute shell/bash command using C/C++
Thanks for any help in advance!
source is not a program that you can call, it is embedded bash command. It is designed to be processed by bash without invoking another copy of bash, such that environment variables can be changed in current bash copy.
However, you cannot call source as part of system(). And even if you did succeed at that, its effects to change environment variables would be completely lost for caller app once system() has returned.
Try a command to envelop with parameters in double quotes ("command - arg1 - to arg2") to transfer in the function system().
used:
char *com = "\"command -arg1 -arg2\"";
system(com);