winapi: CreateProcess but hide the process' window? - c

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

Related

How to write data into global variables from callback function?

According to windows API docs we can use global variable to pass data from creating thread to the new thread and I am assuming the opposite is also possible
Data can also be passed from the creating thread to the new thread using global variables.
Here is a data structure and a callback function, ptr is a pointer to heap allocated memory in main
typedef struct Output
{
char *ptr;
DWORD len;
}Output, *POutput;
Output out; // global variable
DWORD grab_output(LPVOID args)
{
DWORD dread;
BOOL success = FALSE;
while (1)
{
success = ReadFile(g_hChildStd_OUT_Rd,out.ptr, 1024, &dread, NULL);
if (!success || dread == 0 ) break;
out.ptr = realloc(out.ptr, out.len+1024);
out.len += dread;
}
}
int run()
{
BOOL res;
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
DWORD dwThreadIdArray[1];
DWORD n_size;
memset(&si, 0 ,sizeof(si));
memset(&pi, 0, sizeof(pi));
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0))
return GetLastError();
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
return GetLastError();
si.cb = sizeof(STARTUPINFOA);
si.hStdError = g_hChildStd_OUT_Wr;
si.hStdOutput = g_hChildStd_OUT_Wr;
si.dwFlags |= STARTF_USESTDHANDLES;
if(!CreateProcess(NULL,
"C:\\Windows\\System32\\cmd.exe /c dir",
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
))
{
}
else
{
handle = CreateThread(0, 0, grab_output, NULL, 0, NULL);
}
return 0;
}
int main()
{
out.ptr = malloc(1024);
out.len = 0;
run();
printf("%s\n", out.ptr);
}
when running the code out.ptr returns garbage values
gcc example.c && ./a.exe
└e╔┐═☺
for the sake of this question assume that I will be running a single thread at any given time
The reason this prints garbage values is you assumed for no clear reason that the thread finishes before you accessed the global variable.
There's too many unchecked fault points. Right now, check every function that can error for an error return and produce output in that case, and also set a flag in another global variable. Really, you shouldn't have to, but better to much than not enough. Then close the process and thread handles you aren't using.
Now we should be able to discuss synchronization.
It looks like you want to grab all of the output at once. Thus WaitForSingleObject() on your own thread handle. To produce output incrementally, you need to track input highwater and output highwater and output only the characters in between with putc().
Don't forget to null-terminate your string either, or printf() won't be happy.
You need some means to communicate between the thread and main() that the value has been updated. It is very likely that main() will execute the printf before the thread is done with ReadFile. Also you have a race condition where ReadFile might be writing to the buffer while printf is reading it.
Use a mutex, semaphore, event or similar to communcate between threads, then use WaitForSingleObject etc where appropriate. It's also not advisable to have a busy-loop inside the thread or to exit the creator thread main() while there are threads still running.
EDIT:
Note that you must also return 0 from the thread or your program will go haywire, if you somehow managed to get it compiling in the first place despite the missing return.

How do you send commands from a parent process to run on an existing child cmd.exe process?

I have a piece of code that, amongst other things, creates a child cmd.exe process with redirected I/O handles, given a specific input.
HANDLE child_IN_Rd = NULL;
HANDLE child_IN_Wr = NULL;
HANDLE child_OUT_Rd = NULL;
HANDLE child_OUT_Wr = NULL;
SECURITY_ATTRIBUTES sa;
STARTUPINFOW si;
PROCESS_INFORMATION pi;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
CreatePipe(&child_IN_Rd, &child_IN_Wr, sa, 0);
CreatePipe(&child_OUT_Rd, &child_OUT_Wr, sa, 0);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdError = child_OUT_Wr;
si.hStdOutput = child_OUT_Wr;
si.hStdInput = child_IN_Rd;
CreateProcessA("C:\\Windows\\system32\\cmd.exe",
NULL,
NULL.
NULL,
false,
NULL,
NULL,
NULL,
si,
pi)
CloseHandle(child_IN_Rd);
CloseHandle(child_OUT_Wr);
The intent is for the code to run cmd commands at the behest of a remote client. The parent receives a string from the client, and writes it to child_IN_Wr. The cmd.exe process should then run the string as a command, and the output is read on the parent console.
Something like this:
WriteFile(child_IN_Wr, command, command_size, NULL, NULL);
...
ReadFile(child_OUT_Rd, buffer, buffer_size, NULL, NULL);
//Do something with the output, eg. print, or sending it back to client.
printf("%s", buffer);
However, I am unable to get it to work. The existing cmd.exe process does not seem to register/process an input written to child_IN_Wr, and no output is read as a result.
I understand that this issue can be easily fixed by simply running CreateProcess with the given command under the CommandLine parameter, every time the parent receives an input from the remote client. However, this spawns and terminates a new cmd.exe process every time a command is run, and I wish to run all the commands on a single cmd.exe process created beforehand given a specific input from a client, that only terminates after the client sends another specific input.
How should I go about this? I have been trying out the use of pipes for IPC, as seen above, but have had no luck thus far. Thanks in advance.

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;
}

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

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

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*.

Resources