CreateProcess() launching child applications - c++

I want to launching a sub application from the main application using CreateProcess function with the following steps:
launched a sub .exe program from the main without window for the sub program
wait for rand Sleep
then terminate the sub application first then the main.
In the following my example code for the above but the sub program running with window(in this case NotePad) and i can't terminate the sub program.
#include "stdafx.h"
#include <windows.h>
#include <conio.h>
#include <strsafe.h>
#include <direct.h>
#include <string.h>
int main(int argc, char* argv[])
{
HWND hWnd;
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
ZeroMemory(&sInfo, sizeof(sInfo));
sInfo.cb = sizeof(sInfo);
ZeroMemory(&pInfo, sizeof(pInfo));
if (CreateProcess("C:\\WINDOWS\\System32\\notepad.exe", NULL, NULL, NULL, false, CREATE_NO_WINDOW, NULL, NULL, &sInfo, &pInfo))
{
printf("Sleeping 100ms...\n");
Sleep(100);
DWORD dwExitCode;
GetExitCodeProcess(pInfo.hProcess, &dwExitCode);
CloseHandle(pInfo.hThread);
CloseHandle(pInfo.hProcess);
}
system("pause");
return 0;
}

The reason the notepad window shows is because it's not a console application. MSDN says this about CREATE_NO_WINDOW:
The process is a console application that is being run without a console window. Therefore, the console handle for the application is not set.
This flag is ignored if the application is not a console application, or if it is used with either CREATE_NEW_CONSOLE or DETACHED_PROCESS.
Instead, use the STARTUPINFO you pass in:
sInfo.dwFlags = STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_HIDE;
I believe that will affect the last argument to WinMain in Notepad's main function, but I'm not sure.
As for why notepad doesn't close, GetExitCodeProcess doesn't actually end the process, it just retrieves the state. You can use TerminateProcess instead:
TerminateProcess(pInfo.hProcess, 0);

Related

FreeConsole() does not detach application from cmd

I launch my application in cmd. I compiled it by Cmake without WIN32_EXECUTABLE, so it hangs in cmd (i.e. is launched as not detached). Now I want to close the console and try to achieve this by calling FreeConsole().
This works in case I double-click the application -- the black console is flashes quickly and gets closed. But it does not work when I launch it in cmd. The cmd is still attached to the launched application and FreeConsole() does not help.
Is there any way to detach it from cmd programmatically? I have found the opportunity to run start /b myapp, but I would like to do it in a programmatical way.
UPDATE
A rough implementation of the answer of Anders for those who are interested -- see below. In this implementation I pass all the arguments, supplied to main.com, to the child process main.exe.
// main.cpp
// cl main.cpp
// link main.obj /SUBSYSTEM:WINDOWS /ENTRY:"mainCRTStartup"
//
#include <stdio.h>
#include <Windows.h>
int main(int argc, char** argv)
{
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
freopen("CONIN$", "r", stdin);
}
for (int i = 0; i < argc; i++)
printf("--%s", argv[i]);
printf("Hello\n");
int k = 0;
scanf("%d", &k);
printf("%d\n", k);
return 0;
}
// helper.cpp
// cl helper.cpp
// link helper.obj /OUT:main.com
//
#include <windows.h>
#include <stdio.h>
#include <string.h>
void main( int argc, char **argv )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Reconstructing the command line args for main.exe:
char cmdLine[32767] = { 0 };
strcpy(cmdLine, "main.exe ");
int shift = strlen("main.exe ");
for (int i = 1 ; i < argc; i++)
{
strcpy(cmdLine + shift, argv[i]);
const int argLength = strlen(argv[i]);
cmdLine[shift + argLength] = ' ';
shift += (argLength + 1);
}
printf("\n!!!!%s!!!!!%s\n", cmdLine, GetCommandLine());
// Start the child process.
// https://learn.microsoft.com/en-us/windows/win32/procthread/creating-processes
//
if( !CreateProcess(NULL, // No module name (use command line)
cmdLine, // 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 );
}
Creating a "perfect" application that can be both GUI or console is not possible on Windows.
When a .exe has its subsystem set to console, two things happen:
CreateProcess will attach it to the parents console. If the parent does not have one, a new console is created. This can only be suppressed by passing flags to CreateProcess.
cmd.exe will wait for the process to finish.
The trick of setting the subsystem to Windows and using AttachConsole is sub-optimal because cmd.exe will not wait.
The best solution is to create your main .exe as a Windows application. Create another console helper application that you rename from .exe to .com. The helper application will just launch the main app in GUI mode and then quit. In console mode it has to tell the main app that it needs to attach and you need to WaitForSingleObject on it. Example application available here .
Visual Studio uses this .com trick. The trick works because .com is listed before .exe in %pathext%.

c++ how to write to a process that was created with createProcess

I am creating a new Powershell process via createProcess and would like to write a command to that Powershell window and hit Enter. Here is what I have:
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
char myCommand[] = "cmd /c powershell.exe -NoExit";
CreateProcess(NULL, // No module name (use command line)
myCommand, // 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
Sleep(5000);
string strMytestString("ls");
cout << strMytestString.c_str();
Sleep(2000);
// ENTER key down
keybd_event(VK_RETURN, 0x9C, 0, 0);
// ENTER key up
keybd_event(VK_RETURN, 0x9C, KEYEVENTF_KEYUP, 0);
return 0;
}
It opens the powershell and writes "ls" into it and hits Enter but Powershell does not take it as a command and does not do the "ls" but write it as a normal text.
Is there a way to make Powershell execute that command that I pass to it as a String?
Try to read a little bit more about STDIN, STDOUT and STDERR.
To achieve your intention, you have to pass commands into STDIN of child process.
Take a look for MSDN post Creating a Child Process with Redirected Input and Output that shown exactly what you need.

Re-execute a program after machine exception

I have a pre-compiled exe (native C++11) which crashes (access violation error) at some point in iterative process. I can not afford debugging it and re-compile it again for now.
I thought of a dirty solution. I will make another program that is responsible for executing that exe and when it stopped working, I simply re-execute it again.
Is it possible? How can I know that the program was stopped?
Note: I am on Windows and doing development using MSVS.
I have found a solution with help of #Richard Hodges.
Make a new program with the this code:
#include <Windows.h>
#include <string>
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int main(int argc, const char**argv) {
while (true) {
TCHAR ProcessName[256];
STARTUPINFO si;
PROCESS_INFORMATION pi;
wcscpy(ProcessName, L"FaultyProgram.exe");
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
ProcessName, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // 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 0;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
}
And the most important part is to disable UI Error message when a program crash by changing this value in the registry:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Windows Error Reporting
"DontShowUI"=dword:00000001
instead of:
"DontShowUI"=dword:00000000

How to run a Videofile using VLC player Using C++

#include<Windows.h>
#include<direct.h>
int main()
{
_chdir`("C:\\Program Files (x86)\\VideoLAN\\VLC");
system("vlc C:\\Users\\Documents\\Wildlife.wmv");
return 0;
}
By using the above code i am successfully able to run the video using vlc player but as the video finishes,still the VLC player window doesn't get close.How to shut the VLC player window?
Please post your valuable suggestion
Use option --play-and-exit or vlc://quit, namely
system("vlc file:///C:\\Users\\Documents\\Wildlife.wmv --play-and-exit");
or
system("vlc file:///C:\\Users\\Documents\\Wildlife.wmv --vlc://quit");
If you want to use another system call to terminate it, try this on Windows:
system("taskkill /im vlc.exe");
Use CreateProcess to pass the correct commandline. See the example below. Note the use of \" separators.
#include <Windows.h>
int main()
{
const char *appname = "c:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe";
const char *filename = "c:\\files\\my file.wav";
STARTUPINFOA si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
char buf[MAX_PATH + 300];
wsprintfA(buf, "%s \"%s\" --play-and-exit", appname, filename);
CreateProcessA(0, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
return 0;
}
Use Unicode if that's a proper Windows program.
You need to:
Get all process IDs running at that time using EnumProcesses():https://msdn.microsoft.com/en-us/library/windows/desktop/ms682629(v=vs.85).aspx
Call OpenProcess() on each process in that above list and get a HANDLE:http://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx
If you managed to get a HANDLE call GetModuleBaseName() and get the process name:http://msdn.microsoft.com/en-us/library/windows/desktop/ms683196(v=VS.85).aspx
Check the name and if you have found your target process in this case "vlc", call TerminateProcess():http://msdn.microsoft.com/en-us/library/windows/desktop/ms686714(v=VS.85).aspx
This is just a way...

How to execute another exe from a C++ program in Windows

I want my C++ program to execute another .exe, in Windows. How would I do this? I am using Visual C++ 2010.
Here is my code
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
unsigned int input;
cout << "Enter 1 to execute program." << endl;
cin >> input;
if(input == 1) /*execute program here*/;
return 0;
}
This is a solution I found when looking for an answer previously.
It stated that you should always avoid using system() because:
It is resource heavy
It defeats security -- you don't know you it's a valid command or does the same thing on every system, you could even start up programs you didn't intend to start up. The danger is that when you directly execute a program, it gets the same privileges as your program -- meaning that if, for example, you are running as system administrator then the malicious program you just inadvertently executed is also running as system administrator.
Anti virus programs hate it, your program could get flagged as a virus.
Instead CreateProcess() can be used. Createprocess() is used to just start up an .exe and creating a new process for it. The application will run independent from the calling application.
#include <Windows.h>
void startup(LPCSTR lpApplicationName)
{
// additional information
STARTUPINFOA si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcessA
(
lpApplicationName, // the path
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Opens file in a separate console
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
you can use the system function
int result = system("C:\\Program Files\\Program.exe");
Use the CreateProcess() Function.
See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx for details
You can make a call using system
system("./some_command")
I believe this answer should work with different programs, I tested it with Chrome.
// open program.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "string"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string command = "start chrome https://www.google.com/";
system(command.c_str());
return 0;
}