Using CreateProcess, can't get CREATE_NO_WINDOW to supress the console - c

I want to kick off a process (we'll use notepad for simplicity) without the console window popping up.
I'm sure I've missed something very simple, here is my most simplified test case:
#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);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
"notepad", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NO_WINDOW, // 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 );
}

You are creating a new process(notepad.exe) from a parent process(your console application), and let parent process wait for child process to finish. The console window is the main window of your parent process. You can hide and restore is as show below.
// Notice how hiding the console window causes it to disappear from
// the Windows task bar. If you only want to make it minimize, use
// SW_MINIMIZE instead of SW_HIDE.
void _tmain(int argc, TCHAR *argv[])
{
ShowWindow( GetConsoleWindow(), SW_HIDE );
// create a new process and wait for it to finish
ShowWindow( GetConsoleWindow(), SW_RESTORE );
}

Change the application subsystem from Console to Windows. In VS2008, this is under linker properties, System.
Then change your main function to:
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
and change the code to return an int.

This is how you change the application subsystem from Console to Windows using MinGW, add these linker flags:
-Wl,-subsystem,windows

Related

Windows launch process with/without console

I use c system() function in my application to launch commands like these:
cmd.exe /c a.bat
guiapp.exe
consoleapp.exe
It works, however, system() launches guiapp.exe with console displayed (which, obviously, is not used in this gui app). How to launch new process considering the fact that I don't know whether process to be launched should display console? I want to launch the process in the same way as the process would be launched when double clicked by mouse.
You can use CreateProcess and in the dwFlags parameter do not specify CREATE_NEW_CONSOLE as one of the flags.
This way, if the application is a GUI app, it will not launch a console window, and if it is a console app, it will run in the same console as the launching process.
Example code:
#include <Windows.h>
#include <stdio.h>
int main(void)
{
PROCESS_INFORMATION pi, pi2;
STARTUPINFO si, si2;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
CreateProcessW(L"C:\\GUIAppDir\\GUIApp.exe", L"program-arguments-here", NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, NULL, L"C:\\GUIAppDir", &si, &pi);
ZeroMemory(&pi2, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si2, sizeof(STARTUPINFO));
si2.cb = sizeof(STARTUPINFO);
CreateProcessW(L"C:\\ConsoleAppDir\\ConsoleApp.exe", L"program-arguments-here", NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, NULL, L"C:\\ConsoleAppDir", &si2, &pi2);
WaitForSingleObject(pi2.hProcess, INFINITE);
CloseHandle(pi2.hThread);
CloseHandle(pi2.hProcess);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}

Open external program

I've been trying to open an external program like Editor for example in C.
I've searched for hours but haven't found a way to open external executables, e.g. open Skype or so from the Console Application.
This is my code so far:
/* fopen1.c */
#include <Windows.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
int main(int)
{
FILE *fp;
fp = fopen("C://Users/Jonte/Desktop/Skype.exe", "r");
}
How can I open external files?
Thank you,
Sincerely,
Behring
One possible way -
system("C:\\Windows\\notepad.exe");
or
ShellExecute(NULL, "open", "C:\\Windows\\notepad.exe", NULL, NULL, SW_SHOWDEFAULT);
or use CreateProcess
VOID startup(LPCTSTR lpApplicationName)
{
// additional information
STARTUPINFO 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
CreateProcess( lpApplicationName, // the path
argv[1], // 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
)
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}

CreateProcess() fails with an access violation [duplicate]

This question already has answers here:
Unhandled Error with CreateProcess [duplicate]
(2 answers)
Closed 4 years ago.
My aim is to execute an external executable in my program. First, I used system() function, but I don't want the console to be seen to the user. So, I searched a bit, and found CreateProcess() function. However, when I try to pass a parameter to it, I don't know why, it fails. I took this code from MSDN, and changed a bit:
#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);
ZeroMemory( &pi, sizeof(pi) );
/*
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
*/
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
L"c:\\users\\e\\desktop\\mspaint.exe", // 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 );
}
However, this code crated access violation somehow. Can I execute mspaint without showing user the console?
Thank you very much.
The second argument is a LPTSTR, namely a pointer to a non-const char array. The docs specifically say:
this parameter cannot be a pointer to read-only memory (such as a
const variable or a literal string)
The reason passing a string literal is a problem:
The system adds a terminating null character to the command-line
string to separate the file name from the arguments. This divides the
original string into two strings for internal processing.
Which means in your case, it tries to modify read-only memory, hence the crash.
Try this, it should work.
TCHAR lpszClientPath[500]= TEXT("c:\\users\\e\\desktop\\mspaint.exe");
if(!CreateProcess(NULL, lpszClientPath, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT,NULL, NULL, &si, &pi))
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
...
...
Change you code to this:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( int argc, TCHAR *argv[] )
{
TCHAR ProcessName[256];
STARTUPINFO si;
PROCESS_INFORMATION pi;
wcscpy(ProcessName,L"c:\\users\\e\\desktop\\mspaint.exe");
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
/*
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
*/
// 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
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 );
}

Problem in CreateProcess function!

I have my main application ,from my main application I will be calling another
module(third party) to perform a small operation in my main application,when I call that module..it processes for a particular time say 5 sec.while its proccessing it shows the process in the commmand window with some information..now my main application waits until the called module finishes its process.Now my Question is..how to do I hide this command window without disturbing its process..I tried to use the createprocess but it seems to not work...
for example: my main application is the Parent process and the called application is child process..Parent process should be independent of the child process..check my example below
int main()
{
execl("c:\\users\\rakesh\\Desktop\\calledapplication.exe","c:\\users\\rakesh\\Desktop \\calledapplication.exe",0);
}
code in calledapplication
int main
{
printf("Rakesh");
}
now considering the above if you run the first program...output would appear in the same
command window(It shouldnt be like that)...I want the main application to create the process but it should not be affected by child process.
Pass CREATE_NO_WINDOW in the dwCreationFlags parameter of CreateProcess.
You talked about a "command window", so I presume that the child is a console application.
In that case you can create the process in a separate conole and optionally force the new console to be iconified or hidden.
The following code launch a child process that interprets a batch file (mytest.bat).
I hope it can help. Regards.
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL rv = FALSE;
WCHAR cmdline[] = TEXT("cmd.exe /c mytest.bat");
memset(&si,0,sizeof(si));
si.cb = sizeof(si);
// Add this if you want to hide or minimize the console
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; //or SW_MINIMIZE
///////////////////////////////////////////////////////
memset(&pi,0,sizeof(pi));
rv = CreateProcess(NULL, cmdline, NULL, NULL,
FALSE, CREATE_NEW_CONSOLE,
NULL, NULL, &si, &pi);
if (rv) {
WaitForSingleObject(pi.hProcess, INFINITE);
printf("Done! :)\n");
}
else {
printf("Failed :(\n");
}
return rv ? 0 : 1;
}
It sounds like you want the child process's output to show up in a separate window. If so, you want to call CreateProcess and pass it the CREATE_NEW_CONSOLE flag, rather than using exec*.

winapi: CreateProcess but hide the process' window?

I am using CreateProcess to create a cmd.exe process that is passed a parameter that it executes and quits, this makes command prompt flash up on the screen.
I tried to avoid this by setting STARTUPINFO struct wShowWindow to SW_HIDE but this parameter seems to affect the calling window, not the window for the process that gets executed.
Is there anyway that you can use createprocess to launch a program that is hidden from view?
Also what is the proper winapi standard way to get enviroment variables?
If its just a console app you can also use the CREATE_NO_WINDOW flag as part of the CreateProcess call itself, e.g.
CreateProcess(NULL, lpszCommandLine, NULL, NULL, FALSE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
Also, see this page for information about environment variables.
The following link here describes how to create the window silently:
DWORD RunSilent(char* strFunct, char* strstrParams)
{
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
char Args[4096];
char *pEnvCMD = NULL;
char *pDefaultCMD = "CMD.EXE";
ULONG rc;
memset(&StartupInfo, 0, sizeof(StartupInfo));
StartupInfo.cb = sizeof(STARTUPINFO);
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;
Args[0] = 0;
pEnvCMD = getenv("COMSPEC");
if(pEnvCMD){
strcpy(Args, pEnvCMD);
}
else{
strcpy(Args, pDefaultCMD);
}
// "/c" option - Do the command then terminate the command window
strcat(Args, " /c ");
//the application you would like to run from the command window
strcat(Args, strFunct);
strcat(Args, " ");
//the parameters passed to the application being run from the command window.
strcat(Args, strstrParams);
if (!CreateProcess( NULL, Args, NULL, NULL, FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&StartupInfo,
&ProcessInfo))
{
return GetLastError();
}
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
if(!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
rc = 0;
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
return rc;
}
I think getenv and setenv are all okay? I am not sure what you are asking about in that respect.
set the STARTF_USESHOWWINDOW in dwFlags
by sharptooth
This might be an overkill for your needs, but you can hook the ShowWindow API and never show any windows for that process

Resources