Run a CMD command in Qt without displaying the CMD window
It's necessary to execute system commands sometime. system() is the most basic, it's easy but cannot hide the black command line window, its options are not much enough. Here're some better ways.
Method 1: system
It’s the most basic method not only used in Qt, you should include the library stdlib.h
.
But, you have to see the ugly black cmd window.
Header |
---|
stdlib.h |
Syntax
1
int system (const char* command);
Parameters
command
:
C-string containing the system command to be executed.
Or, alternatively, a null pointer, to check for a command processor.Return Value
If command is a null pointer, the function returns a non-zero value in case a command processor is available and a zero value if it is not.
If command is not a null pointer, the value returned depends on the system and library implementations, but it is generally expected to be the status code returned by the called command, if supported.Example
1
2
3
4
5
6
7
8
9
10
11
12
13
/******example: ping******/
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("checking processor\n");
if (system(NULL)) puts ("Ok");
else exit (EXIT_FAILURE);
printf("start ping\n");
system("ping localhost >> res.txt");
return 0;
}
You can see the ping’s result in res.txt
after running these code.
Is here some method I can take to avoid displaying the cmd window? The answer is: YES.
Method 2: WinExec – without cmd window
WinExec()
is another way to run a command, the advantage of using WinExec()
is you don’t need to display the window, it means, you can hide the window. It needs winbase.h
& windows.h
.
BUT, this function is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess()
function(as follows).
Header |
---|
windows.h winbase.h |
Syntax
1
2
3
4
UINT WinExec(
LPCSTR lpCmdLine,
UINT uCmdShow
);
Parameters
lpCmdLine
:
The command line (file name plus optional parameters) for the application to be executed.
uCmdShow
:
The display options.
List of the acceptable values:
Value | Meaning |
---|---|
SW_HIDE 0 | Hides the window and activates another window. |
SW_SHOWNORMAL SW_NORMAL 1 | Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time. |
SW_SHOWMINIMIZED 2 | Activates the window and displays it as a minimized window. |
SW_SHOWMAXIMIZED SW_MAXIMIZE 3 | Activates the window and displays it as a maximized window. |
SW_SHOWNOACTIVATE 4 | Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except that the window is not activated. |
SW_SHOW 5 | Activates the window and displays it in its current size and position. |
SW_MINIMIZE 6 | Minimizes the specified window and activates the next top-level window in the Z order. |
SW_SHOWMINNOACTIVE 7 | Displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except the window is not activated. |
SW_SHOWNA 8 | Displays the window in its current size and position. This value is similar to SW_SHOW, except that the window is not activated. |
SW_RESTORE 9 | Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window. |
SW_SHOWDEFAULT 10 | Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess() function by the program that started the application. |
SW_FORCEMINIMIZE 11 | Minimizes a window, even if the thread that owns the window is not responding. This flag should only be used when minimizing windows from a different thread. |
Return value
If the function succeeds, the return value is greater than 31.
If the function fails, the return value is one of the following error values.
Return code/value | Description |
---|---|
0 | The system is out of memory or resources. |
ERROR_BAD_FORMAT | The .exe file is invalid. |
ERROR_FILE_NOT_FOUND | The specified file was not found. |
ERROR_PATH_NOT_FOUND | The specified path was not found. |
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/******example: ping******/
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
int main()
{
printf("start ping\n");
WinExec("cmd.exe /c ping localhost >> res.txt", SW_HIDE);
/*
'/c' can't be ignored as you have arguments after 'cmd.exe'
*/
return 0;
}
With this function you cannot determine whether the command is completed, because it is executed asynchronously.
You must use CreateProcess()
to solve the problem.
Method 3: CreateProcess – without cmd window
This function is used to run a new program. It creates a new process and its primary thread. The new process executes the specified executable file.
Header |
---|
windows.h |
Syntax
1
2
3
4
5
6
7
8
9
10
11
12
BOOL CreateProcess(
LPCWSTR lpszImageName,
LPCWSTR lpszCmdLine,
LPSECURITY_ATTRIBUTES lpsaProcess,
LPSECURITY_ATTRIBUTES lpsaThread,
BOOL fInheritHandles,
DWORD fdwCreate,
LPVOID lpvEnvironment,
LPWSTR lpszCurDir,
LPSTARTUPINFOW lpsiStartInfo,
LPPROCESS_INFORMATION lppiProcInfo
);
Parameters
lpszImageName
:
Pointer to a null-terminated string that specifies the module to execute.
The string can specify the full path and filename of the module to execute or it can specify a partial path and filename.
The lpszImageName
parameter must be non-NULL and must include the module name.
lpszCmdLine
:
Pointer to a null-terminated string that specifies the command line to execute. The system adds a null character to the command line, trimming the string if necessary, to indicate which file was actually used.
The lpszCmdLine
parameter can be NULL. In that case, the function uses the string pointed to by lpszImageName
as the command line.
If both lpszImageName
and lpszCmdLine
are non-NULL, *lpszImageName
specifies the module to execute, and *lpszCmdLine
specifies the command line. C runtime processes can use the argc
and argv
arguments.
If the filename does not contain an extension, .EXE is assumed. If the filename ends in a period (.) with no extension, or the filename contains a path, .EXE is not appended.
lpsaProcess
:
Process safety attributes
lpsaThread
:
Thread safety attributes
fInheritHandles
:
Whether to inherit the attributes of the parent process
fdwCreate
:
Specifies additional flags that control the priority class and the creation of the process. The following creation flags can be specified in any combination, except as noted:
Value | Description |
---|---|
CREATE_DEFAULT_ERROR_MODE | Not supported. |
CREATE_NEW_CONSOLE | The new process has a new console, instead of inheriting the parent’s console. This flag cannot be used with the DETACHED_PROCESS flag. |
CREATE_NEW_PROCESS_GROUP | Not supported. |
CREATE_SEPARATE_WOW_VDM | Not supported. |
CREATE_SHARED_WOW_VDM | Not supported. |
CREATE_SUSPENDED | The primary thread of the new process is created in a suspended state, and does not run until the ResumeThread function is called. |
CREATE_UNICODE_ENVIRONMENT | Not supported. |
DEBUG_PROCESS | If this flag is set, the calling process is treated as a debugger, and the new process is a process being debugged. Child processes of the new process are also debugged. The system notifies the debugger of all debug events that occur in the process being debugged. |
If you create a process with this flag set, only the calling thread (the thread that called CreateProcess) can call the WaitForDebugEvent function. |
|
DEBUG_ONLY_THIS_PROCESS | If this flag is set, the calling process is treated as a debugger, and the new process is a process being debugged. No child processes of the new process are debugged. The system notifies the debugger of all debug events that occur in the process being debugged. |
DETACHED_PROCESS | Not supported. |
lpvEnvironment
:
Pointer to current environment.
lpszCurDir
:
Pointer to current directory.
lpsiStartInfo
:
Pointer to STARTUPINFO structure
lppiProcInfo
:
Pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.
Example
Here’s the Microsoft’s example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.wShowWindow = SW_HIDE; //hide window
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
"cmd.exe /c ping localhost >> res.txt", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
Method 4: QProcess – without cmd window
The QProcess class is used to start external programs and to communicate with them. It’s a modern method to run a command.
Header | QProcess |
---|---|
qmake | QT += core |
Examples
1
2
3
4
QProcess p(0);
p.start("cmd", QStringList()<<"/c"<<"ping localhost >> res.txt");
p.waitForStarted();
p.waitForFinished();
Another way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
QProcess p(0);
QString command = "cmd.exe";
QStringList args;
args.append("/c");
args.append("ping");
args.append("localhost");
args.append(">>");
args.append("res.txt");
p.execute(command, args);
p.waitForFinished();
//p.start(command, args);
//p.waitForStarted();
//p.waitForFinished();
Full example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//file: "mainwindow.h"
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void openProcess();
void readResult(int exitCode);
private:
QProcess *p;
};
#endif // MAINWINDOW_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//file: "mainwindow.cpp"
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
p = new QProcess(this);
QPushButton *bt = new QPushButton("execute", this);
connect(bt, SIGNAL(clicked()), this, SLOT(openProcess()));
}
MainWindow::~MainWindow()
{
}
void MainWindow::openProcess()
{
p->start("cmd.exe", QStringList() << "/c" << "ping localhost >> res.txt");
connect(p, SIGNAL(finished(int)), this, SLOT(readResult(int)));
}
void MainWindow::readResult(int exitCode)
{
if(exitCode == 0)
{
QTextCodec* gbkCodec = QTextCodec::codecForName("GBK");
QString result = gbkCodec -> toUnicode(p -> readAll());
}
}
At last
At last, I recommand QProcess and CreateProcess.