showing cmd terminal in qt widgets application - c++

I'm trying to pass some cmd commands using system() and I would like to be able to "communicate" with cmd, say I code in system("dir") in my mainwindow.cpp under my clicked function
this is what it looks like for example
void MainWindow::on_pushButton_login_clicked()
{
std::string platform_server_ip = ui->lineEdit_platform_server_ip->text().toStdString();
if (platform_server_ip == "dir"
{
QMessageBox::information(this,"Login", "all required log in details are correct");
close();
const char* c = platform_server_ip.c_str();
system(c);
system("ipconfig");
}
I would like to know why it behaves like this and if that's normal. I've included CONFIG += console
in my project file, and checked "run in terminal" (tried it also without) but it never shows me my desired outcome.
Instead what I get, is a blank terminal that pops up along side my GUI, and then when I enter "dir" in my GUI and hit enter, a cmd window pops up really fast and in less than a second, its gone. I've even tried it with system("ipconfig")andsystem ("pause")
as well as with one system command like this system("ipconfig" "&pause")
desired outcome: is just a normal execution of system("ipconfig"), followed by other system commands, that display the same result as typing them in cmd itself.
I've also tried all this in "qt Console application" and I either get the same result, or the output (what would normally be as output on cmd) is then found in "application output" of qt creator.
Is there another better way I can achieve what I want?
I'm truly a noob and would really appreciate some guidance.

You can try
system("cmd /k ipconfig");
This will open another terminal window which will stay open (k stands for keep) at the end of the command execution.
I think you don't need the CONFIG += console project setting, to achieve this. Calling system will start another process, which isn't related at all with the calling application.
If you want to start external programs from within a Qt application, you can use QProcess class, which lets you somehow interact with the started processes through standard in/out. For a very simple example, have a form with a push button and a text edit called textEdit; in the push button clicked slot:
QProcess process;
process.start("ipconfig");
process.waitForReadyRead();
ui->textEdit->setText(process.readAll());
process.waitForFinished();
This way, you won't see additional console windows, and the command output will be shown directly in your text edit.
This can be generalized in a function like this:
bool exec(QString command)
{
QProcess process;
process.start(command);
if(!process.waitForStarted())
{
return false; //the process failed to start
}
//etc...
return true;
}

Depending on whether this is not just a quick hack/tool, you can look at QProcess for more indepth control over your process so that you can read / write the child process pipes.

Related

How to run Python script from QT creator and print output to GUI

void MainWindow::on_pushButton_clicked()
{
QProcess p;
// get values from ini file
settings->setValue("EMail", ui->lineEditEMail->text());
settings->setValue("Password", ui->lineEditPassword->text());
settings->setValue("Chronological", ui->checkBox->isChecked());
settings->setValue("Current_info", ui->checkBox_2->isChecked());
settings->endGroup();
settings->sync();
// launch python code for login
QString program( "C:/projects/build-test3-Desktop_Qt_6_4_0_MinGW_64_bit-Debug/venv/Scripts/python.exe");
QStringList args = QStringList() << "index.py";
QProcess::execute( program, args );
}
I have this function that is executed after a button is clicked and I need to print the output of "index.py" in to my app. What widget should I use and how? From what I read QTextBrowser should do the trick but I'm not sure how to use it.
This is how my GUI looks like. I'd like to use to output my results somewhere in button right. I didn't add the widget yet, because I'm not sure QTextBrowser is the one I need
The widget you could use for this purpose is QTextEdit (you can set it to be read-only from the graphical user interface).
But if you want to get the output of the execution, you will need a proper instance of QProcess and call the QProcess::readAllStandardOutput() member function to get the standard output.
You may also be interested by QProcess::readAllStandardError() to get the errors in case of failure.
Edit (simple/basic example):
QProcess p;
p.start("path/to/python.exe", QStringList("script.py"));
p.waitForFinished();
QByteArray p_stdout = p.readAllStandardOutput();
QByteArray p_stderr = p.readAllStandardError();
// Do whatever you want with the results (check if they are not empty, print them, fill your QTextEdit contents, etc...)
Note: If you don't want to be blocking with QProcess::waitForFinished(), you can use a signal/slots connection on QProcess::finished() signal.

Directly executing a batch through clicked function in qt

So I'm trying to have my "button" directly execute a Batch file, important here is that I don't want it to show me a dialogue and make me chose the path, which is the problem I'm having right now with the following code
void MainWindow::on_pushButton_clicked()
{
QString filename=QFileDialog::getOpenFileName(
this,
tr("Open File"),
"C://",
"All files (*.*);;Text File (*.txt);;Music file (*.mp3)");
}
I think this is probably really simple, but i can't get it, I'm not even learning c++ at the moment but my boss asked me to create something out of my scope (wants me to create a GUI for a batch file and have them interact) and I thought of this approach, which is just creating a GUI that executes it.
I've looked at this question: asked to execute an external program with Qt
but they don't talk about how the file path can directly be added into the code, or if I should even be using Qprocess and how, and if I can pass it through "clicked" function.
I'm really inexperienced, all of the code above I got with the help of the internet, but I really don't know how to program using c++
so could someone please be kind enough to show me how a file path can be added to the code, assuming it's in C:\Users\name_goes_here\Downloads
I'd really appreciate it :D
I'd recommend using QProcess for anything "execute external program" with Qt.
You could do it like this:
void MainWindow::on_pushButton_clicked()
{
QProcess process;
process.start("C:/Users/name_goes_here/Downloads/yourfile.bat");
process.waitForFinished(); // Assuming that you do want to wait for it to finish before the code execution resumes
}
Note the "/" in the path. Only Windows uses the messed up "\" for path separation, which would require you to write "C:\\Users\\.." in any string in C++ as "\" needs to be escaped.
Luckily, Qt uses "/" as the universal separator and translates it to whatever the OS needs as required. So you should just use "/" whenever working with Qt.
This is from the Qt documentation:
Qt uses "/" as a universal directory separator in the same way that "/" is used as a path separator in URLs. If you always use "/" as a directory separator, Qt will translate your paths to conform to the underlying operating system.
And finally, if you don't know how to code in C++, shouldn't you be learning that first instead of trying to execute batch files from within a library as complex as Qt? Sounds like you're trying to do too many new things at once.
This is fairly simple merging your source and the one you linked:
void MainWindow::on_pushButton_clicked()
{
QProcess::execute(
QString::fromLatin1(
"cmd.exe /c C:\\Users\\name_goes_here\\Downloads\\file.bat"));
}
Notes:
I used QProcess::execute() instead of QProcess::start() to make things even simpler.
To achieve execution of the batch file, I pass it to cmd32.exe as this is the interpreter which is responsible.
As MCVE testQProcessBatch.cc:
// Qt header:
#include <QtWidgets>
void on_pushButton_clicked()
{
#if 0 // WORKS:
QProcess::execute(
QString::fromUtf8("cmd.exe /c C:\\Users\\Scheff\\Downloads\\testBatch.bat"));
#else // WORKS AS WELL:
QProcess::execute(
QString::fromUtf8("C:\\Users\\Scheff\\Downloads\\testBatch.bat"));
#endif // 0
}
int main(int argc, char **argv)
{
qDebug() << "Version:" << QT_VERSION_STR;
// main application
QApplication app(argc, argv);
QMainWindow qWin;
QPushButton qBtn(QString::fromLatin1("Start cmd"));
qWin.setCentralWidget(&qBtn);
qWin.show();
QObject::connect(&qBtn, &QPushButton::clicked,
&on_pushButton_clicked);
// run application
return app.exec();
}
and the test batch file testBatch.bat:
echo "This is testBatch.bat"
pause
Tested with VS2013 on Windows 10:
Thanks for contributing guys!
I tried using the QProcess method but I think I'm too inexperienced when it comes to figuring out problems associated with it (which I did face when using this method). the CMD route is probably good but I also thought it was too difficult and both of these methods didn't work for me.
Here's what I have now (thanks to Detonar and ymoreau) and and it seems to be doing the job, this might not be the most optimal approach, but it worked for me!
I included QDesktopServices and QUrl
void MainWindow::on_pushButton_clicked()
{
QString filename="C:\\Users\\Name_goes_here\\Downloads\\test.bat";(
this);
hide(); //optional
QDesktopServices::openUrl(QUrl("file:///"+filename,QUrl::TolerantMode));
}

Display QProcess output in another window

I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}

How can I access the Apple Events "openFile" event in C++?

I'm interested in writing a small utility in C++ for Mac OS X to read, parse, save (over)write a file. I don't need any GUI, menus, or windows.
What type of project template do I need to start with in XCode?
How can I access the file that is passed in? (It's passed with Apple Events openFile, right?)
I've done a little C++ but nothing on Mac. Links appreciated, code samples appreciated more.
How do you intend to pass files to your application?
If it's via the command line then you would use the Command Line Tool template and access the command line parameters just as you would on any POSIX platform (argc and argv).
If you want to pass files to your application using Finder, say, by dropping files onto the application icon, then you would use the Cocoa Application template.
The Info.plist file contains your application configuration and supported document types, similar to the registry on Windows.
You configure Info.plist via the "Info" tab of your Project Settings (It's the top-most file in the file navigator in XCode). Click the "Add" button in the lower right, then select "Add Document Type" to add a document type that your application will accept. To accept all documents, set the document name to All and set the extension to *. More info is here.
Add a LSUIElement key in your Info.plist, and set its value to YES to indicate that your application has no UI. This key is also displayed as "Application is agent" in XCode. More info on LSUIElement is here.
In your MainMenu.xib, you can delete the Window and Font Manager objects that are there by default, since you won't be needing them.
Rename the AppDelegate.m file to AppDelegate.mm, so that it's compiled as Objective-C++. This will allow you to use C++ code in that file.
In the applicationDidFinishLaunching: delegate method, add [NSApp terminate:nil]; so that your app quits immediately when it's done its work.
Add the following method to AppDelegate.mm:
- (BOOL)application:(NSApplication*)app openFile:(NSString *)filename
{
NSLog(#"Opening file %#", filename);
char* cFilename = [filename UTF8String];
// Your C++ code goes here
return YES;
}
That's it. The rest is your C++ code. You can add any C++ code to AppDelegate.mm that you want. E.g.:
#include <string>
#include <iostream>
#include "MyCppFileProcessor.h"
- (BOOL)application:(NSApplication*)app openFile:(NSString *)filename
{
std::string cFilename([filename UTF8String]);
std::cout << "Processing file: " << cFilename << std::endl;
MyCppFileProcessor fileProcessor;
fileProcessor.processFile(cFilename);
return YES;
}
This code will run whenever you drop a document onto your Application's icon in Finder.
1)Use the Command Line Tool template. There are several options for this template. You may select C++ from the menu.
2)As far as I know IOstream will work just fine. Also, there's an argument parameter on your main() function, you may get the file name from these args.
http://www.cplusplus.com/reference/iostream/

How do I make Visual Studio pause after executing a console application in debug mode?

I have a collection of Boost unit tests I want to run as a console application.
When I'm working on the project and I run the tests I would like to be able to debug the tests, and I would like to have the console stay open after the tests run.
I see that if I run in release mode the console window stays up after the program exits, but in debug mode this is not the case.
I do not want to add 'system("pause");' or any other hacks like reading a character to my program. I just want to make Visual Studio pause after running the tests with debugging like it would if I were running in release mode. I would also like it if the output of tests were captured in one of Visual Studio's output windows, but that also seems to be harder than it should be.
How can I do this?
Try to run the application with the Ctrl + F5 combination.
http://connect.microsoft.com/VisualStudio/feedback/details/540969/missing-press-any-key-to-continue-when-lauching-with-ctrl-f5
In the older versions it would default to the console subsystem even if you selected "empty project", but not in 2010, so you have to set it manually. To do this select the project in the solution explorer on the right or left (probably is already selected so you don't have to worry about this). Then select "project" from the menu bar drop down menus, then select "project_name properties" > "configuration properties" > "linker" > "system" and set the first property, the drop down "subsystem" property to "console (/SUBSYSTEM:CONSOLE)". The console window should now stay open after execution as usual.
Boost test offers the following usage recommendations for Visual Studio that would enable you to run the unit tests automatically at the end of compilation and capture the output into the build window.
The nice side effect of this trick is it enable you to treat test failures as compilation errors. "...you could jump through these errors using usual keyboard shortcuts/mouse clicks you use for compilation error analysis..."
Set a breakpoint on the last line of code.
I just copied from http://social.msdn.microsoft.com/forums/en-US/Vsexpressvc/thread/1555ce45-8313-4669-a31e-b95b5d28c787/?prof=required:
The following works for me :-)
/////////////////////////////////////////////////////////////////////////////////////
Here is another reason the console may disappear. And the solution:
With the new Visual Studio 2010 you might see this behavior even when you use Ctrl + F5 aka "start without debugging". This is most likely because you created an "empty project" instead of a "Win32 console application". If you create the project as a "Win32 console application" you can disregard this as it does not apply.
In the older versions it would default to the console subsystem even if you selected "empty project", but not in Visual Studio 2010, so you have to set it manually. To do this select the project in the solution explorer on the right or left (probably is already selected so you don't have to worry about this).
Then select "project" from the menu bar drop down menus, then select "project_name properties" → "configuration properties" → "linker" → "system" and set the first property, the drop down "subsystem" property to "console (/SUBSYSTEM:CONSOLE)". The console window should now stay open after execution as usual.
/////////////////////////////////////////////////////////////////////////////////////
If it is a console application, use Ctrl + F5.
In Boost.Test there is the --auto_start_dbg parameter for breaking into the debugger when a test fails (on an exception or on an assertion failure). For some reason it doesn't work for me.
See http://www.boost.org/doc/libs/1_40_0/libs/test/doc/html/utf/usage-recommendations/dot-net-specific.html
For this reason I have created my custom test_observer that will break into the debugger when there is an assertion failure or an exception. This is enabled on debug builds when we are running under a debugger.
In one of the source files of my unit test EXE file I have added this code:
#ifdef _DEBUG
#include <boost/test/framework.hpp>
#include <boost/test/test_observer.hpp>
struct BoostUnitTestCrtBreakpointInDebug: boost::unit_test::test_observer
{
BoostUnitTestCrtBreakpointInDebug()
{
boost::unit_test::framework::register_observer(*this);
}
virtual ~BoostUnitTestCrtBreakpointInDebug()
{
boost::unit_test::framework::deregister_observer(*this);
}
virtual void assertion_result( bool passed /* passed */ )
{
if (!passed)
BreakIfInDebugger();
}
virtual void exception_caught( boost::execution_exception const& )
{
BreakIfInDebugger();
}
void BreakIfInDebugger()
{
if (IsDebuggerPresent())
{
/**
* Hello, I know you are here staring at the debugger :)
*
* If you got here then there is an exception in your unit
* test code. Walk the call stack to find the actual cause.
*/
_CrtDbgBreak();
}
}
};
BOOST_GLOBAL_FIXTURE(BoostUnitTestCrtBreakpointInDebug);
#endif
You say you don't want to use the system("pause") hack. Why not?
If it's because you don't want the program to prompt when it's not being debugged, there's a way around that. This works for me:
void pause () {
system ("pause");
}
int main (int argc, char ** argv) {
// If "launched", then don't let the console close at the end until
// the user has seen the report.
// (See the MSDN ConGUI sample code)
//
do {
HANDLE hConsoleOutput = ::GetStdHandle (STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE == hConsoleOutput)
break;
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (0 == ::GetConsoleScreenBufferInfo (hConsoleOutput, &csbi))
break;
if (0 != csbi.dwCursorPosition.X)
break;
if (0 != csbi.dwCursorPosition.Y)
break;
if (csbi.dwSize.X <= 0)
break;
if (csbi.dwSize.Y <= 0)
break;
atexit (pause);
} while (0);
I just paste this code into each new console application I'm writing. If the program is being run from a command window, the cursor position won't be <0,0>, and it won't call atexit(). If it has been launched from you debugger (any debugger) the console cursor position will be <0,0> and the atexit() call will be executed.
I got the idea from a sample program that used to be in the MSDN library, but I think it's been deleted.
NOTE: The Microsoft Visual Studio implementation of the system() routine requires the COMSPEC environment variable to identify the command line interpreter. If this environment variable gets messed up -- for example, if you've got a problem in the Visual Studio project's debugging properties so that the environment variables aren't properly passed down when the program is launched -- then it will just fail silently.
It would actually be more effort, but you could just build in VS.Net, run it from the regular command line (cmd.exe), and then attach to the process after it starts running. This is probably not the solution you are looking for however.
Or you could use boost_test "Test Log Output."
http://www.boost.org/doc/libs/1_47_0/libs/test/doc/html/utf/user-guide/test-output/test-log.html
Then it won't matter whether the console window shows up at all AND your build logging can preserve the unit testing output as an artifact for examination on failed builds...
Adding the following line will do a simple MS-DOS pause displaying no message.
system("pause >nul | set /p \"=\"");
And there is no need to Ctrl+F5 (which will make your application run in Release Mode)
I would use a "wait"-command for a specific time (milliseconds) of your own choice. The application executes until the line you want to inspect and then continues after the time expired.
Include the <time.h> header:
clock_t wait;
wait = clock();
while (clock() <= (wait + 5000)) // Wait for 5 seconds and then continue
;
wait = 0;
You could also setup your executable as an external tool, and mark the tool for Use output window. That way the output of the tool will be visible within Visual Studio itself, not a separate window.
I start the app with F11 and get a breakpoint somewhere in unit_test_main.ipp (can be assembly code). I use shift-f11 (Step out) to run the unit test and get the next assembly instruction in the CRT (normally in mainCRTStartup()). I use F9 to set a breakpoint at that instruction.
On the next invocation, I can start the app with F5 and the app will break after running the tests, therefore giving me a chance to peek at the console window
Just use a logging library, like log4net, and have it log to a file appender.
Prompt for user input.
https://www.youtube.com/watch?v=NIGhjrWLWBo
shows how to do this for C++. For Node.js, this is taken right from the docs (and it works):
'use strict';
console.log('Hello world');
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Press enter to continue...', (answer) => {
rl.close(); /* discard the answer */
});
Do a readline at the end (it's the "forma cochina", like we say in Colombia, but it works):
static void Main(string[] args)
{
.
.
.
String temp = Console.ReadLine();
}