Launching IE using system() causes hang for first time - c++

I have used system() to launch IE in my C++ code on a button click. The IE gets launched but a cmd window gets opened too and it gets hanged. I close the cmd window and then it works smoothly. Why is there an initial hang when i first launch the IE?

The cause is that the system() opens a console and calls the command from there. The console only closes when the Internet Explorer closes.
Either use CreateProcess or you can work-around it with system() as well by using the START command:
system("start \"Internet Explorer\" \"C:\\Program Files\\Internet Explorer\\iexplore.exe\" www.google.com");

This code will launch IE using CreateProcess.
However, you may want to use ShellExecute (ShellExecute(NULL, "open", "www.google.com", NULL, NULL, SW_SHOWDEFAULT);) which will use the users default browser.
const char *pathToExplorer = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
const char *webPage = "www.google.com";
char szCmdLine[1024];
sprintf(szCmdLine, "\"%s\" \"%s\"", pathToExplorer, webPage);
STARTUPINFO si = {0};
PROCESS_INFORMATION lp;
si.cb = sizeof(STARTUPINFO);
::CreateProcess( NULL,
szCmdLine,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&lp);

Related

Kill a process that run in infinite loop

I create a process from c++ code, that run a python script.
STARTUPINFO si = {0};
PROCESS_INFOMATION pi = {0};
LPTSTR cmdArgs = _T("cmd.exe /k python myScript.py");
CreateProcess(NULL, cmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
The script run in infinite loop, for example:
while (1):
print("hello")
I want to kill the process but nothing really work.
I t ried TerminateProcess(), taskkill with pid - they report that process terminated but it still running.
How can I kill the process while it runnning?
LPTSTR cmdArgs = _T("cmd.exe /k python myScript.py");
CreateProcess(NULL, cmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
this code create cmd.exe process and it create python.exe process. question - for what create intermediate cmd.exe ?! you need direct start python.exe. use "python myScript.py" command line and start python.exe direct (if use unicode W api and empty application name - string must not be readonly (in your code it readonly - so you use A api, otherwice you got exception))
TerminateProcess not work - because you have handle of cmd.exe and you can terminate it. but not python.exe.
taskkill with pid - they report that process terminated but it still
running.
of course - pid belong to cmd.exe and it terminated. but python.exe still runing.
so again - solution very simply - direct exec target process, without cmd.exe

The Command CreateProcess C++

The Command CreateProcess With the command WaitForSingleObject
can to open an image?
If Yes How can I open the image?
I tried to open but i don't know Where to put the path to open
if (CreateProcess(NULL, "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Paint.lnk", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
If you just want to open an existing image using defualt app then use ShellExectue API. For example:
ShellExecuteW(NULL, L"open", L"Z:\\cat.PNG", NULL, NULL, SW_SHOW);
You could also open image with mspaint using the same API:
ShellExecuteW(NULL, L"open", L"C:\\Windows\\system32\\mspaint.exe", L"Z:\\cat.PNG", NULL, SW_SHOW);
ShellExecuteEx will let you wait for finishing process.
You can do the same using CreateProcess. As #DavidHeffernan pointed out the second parameter of CreateProcess should point to writable memory else it will raise access violation. To make it clear I will just omit the first parameter. Example:
STARTUPINFOW process_startup_info{ 0 };
process_startup_info.cb = sizeof(process_startup_info); // setup size of strcture in bytes
PROCESS_INFORMATION process_info{ 0 };
wchar_t commandline_args[] = L"\"C:\\Windows\\system32\\mspaint.exe\" Z:\\cat.PNG";
if (CreateProcessW(NULL, commandline_args, NULL, NULL, TRUE, 0, NULL, NULL, &process_startup_info, &process_info))
{
//WaitForSingleObject(process_info.hProcess, INFINITE); // uncomment to wait till process finish
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
}
I strongly recommend to read this CodeProject article (A newbie's elementary guide to spawning processes).
The CreateProcess function can only start .exe and .bat files. Use ShellExecute[Ex] if you want to launch files the same way the shell/Explorer does.
A process must have a PE EXE file as its main file and if you ask CreateProcess to start something else it is just going to fail. ShellExecute will look up the file extension in the registry to find the correct executable (or COM handler) to execute and this often ends up calling CreateProcess on your behalf with the file you specified as a command line parameter.
Using ShellExecuteEx with the SEE_MASK_NOCLOSEPROCESS flag might might give you a process handle you can wait on but you also have to be prepared for hProcess being NULL. This can happen if the registered application for the file type is already running and DDE or COM was used to open the file in this existing application instance...

How to open a program and make it run on the currently open console app in C++ [duplicate]

When I call CreateProcess in Windows, the new process doesn't seem to inherit the console of the calling process. I made a test program that runs "ruby xtest", xtest being a script that writes "hello" to standard output. I ran this test program from Emacs, and get no output. I also tried the following code calling GetStdHandle, but again, no output. Then I tried passing CREATE_NEW_CONSOLE in dwCreationFlags to CreateProcess, which made a whole new window with the Ruby output. Finally, I made a simple fork/exec
test program and compiled it using Cygwin's GCC. This program worked: the Ruby output showed up in Emacs as expected. I tried to decipher the Cygwin source code in http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/spawn.cc?rev=1.268&content-type=text/x-cvsweb-markup&cvsroot=src but failed. So, how do you make the new process inherit the console of the parent process such that the output from the child shows up as expected?
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess(0, "ruby xtest", 0, 0, 1, 0, 0, 0, &si, &pi)) die("CreateProcess");
I know, this thread is rather old, however, I just ran into the same problem.
Just as for the TS, the console handle was inherited and working fine under Cygwin, but not on a Windows console. Instead, the output on stdout was neither shown, nor any error was reported. Inherited Pipe handles worked still fine.
I took me some time to identify the (now obvious) problem: CreateProcess() was called with CREATE_NO_WINDOW. Dropping this flag, console output is fine. (Though, according to the code of the TS, they never set this flag in the first place.)
Hope this might be helpful for people who also stumble across this thread, like myself.
According to Microsoft documentation, lpCommandLine (2. parameter):
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
When I stopped using a constant here it worked for me. I didn't need the STARTF_USESTDHANDLES and GetStdHandle thing.
This code from a console prg runs and outputs another console exe in the same console:
FillChar(SI, SizeOf(SI), 0);
SI.cb:=SizeOf(SI);
FillChar(PI, SizeOf(PI), 0);
if CreateProcess(nil, CmdLineVar, nil, nil, False, 0, nil, nil, SI, PI) then ...
I've done this by passing in pipes for hStdInput, hStdOutput, and hStdError and manually routing data from the hStdOutput and hStdError pipes to the console.
Not sure if debeige ever solved this, but I needed the same thing, but starting up another thread to listen to stdout output, just to put it on stdout seemed nuts to me.
The following works for me, and is slightly different than what he originally posted. I thought at first it wouldn't work if you don't set si.cb, but when I commented that in mine, it still worked, so... YMMV.
STARTUPINFO siStartInfo;
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = GetStdHandle(STD_OUTPUT_HANDLE);
siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
siStartInfo.hStdInput = g_hChildStd_IN_Rd; // my outgoing pipe
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bSuccess = CreateProcess(
NULL,
szCmdline,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&siStartInfo,
&piProcInfo);

running a gui program in the background

i created a windows service that will run another program. but now i want to run a program that has a gui but in the background so i don't want the gui to be visible. this is the code i used for the service
But i can't edit the gui program
is there a way to set the gui to hidden or set visible = false from the service program?
the service is a windows service created in c++ using visual studios
i used CreateProcess to start the exe file
here's the code i'm using to run the program from the service:
path = "C:\MyDirectory\MyFile.exe";
STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcess(path, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
::WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
is it possible to hide a gui without editing the program itself?
The closest you are likely to get will be setting the wShowWindow member of the STARTUPINFO structure. Even then it will only work if the application honors the nCmdShow parameter in WinMain.
STARTUPINFO info = {0};
info.dwFlags = STARTF_USESHOWWINDOW;
info.wShowWindow = SW_HIDE;
if (CreateProcess(path, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
//...
}

Is there a way to launch an executable that doesn't have an executable extension?

I have two separate executable files, A.exe & B.dontrun, where A.exe launches B.dontrun after doing some initialization. The two processes then communicate to each other and A.exe exits after B.dontrun exits. This all behaves fine using CreateProcess and passing the executable name as the first argument when B.dontrun is named B.exe but if B.dontrun is named anything else (B.ex_ or B.bin) CreateProcess doesn't return an error, but the process isn't launched either.
I'd like B.dontrun to be named something that doesn't encourage people to run it directly, when they look in the directory they see A.exe and B.dontrun and there isn't confusion of which executable that they should be running.
At least up till and including Windows XP, the [cmd.exe] command interpreter recognizes a PE executable as such regardless of the filename extension, and runs it.
Which is one reason why it's not a good idea to start a text document with the letters "MZ"... ;-)
And which means that it’s not a good idea to try to prevent execution via filename mangling.
Instead, make the other process a DLL, and launch it via rundll32.
Cheers & hth.,
You need to specify the exe name in the cmd line argument rather than in the application name.
This works:
STARTUPINFO info;
ZeroMemory(&info, sizeof(info)); info.cb = sizeof(info);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
TCHAR sz[1000]; // Note: lpCommandLine must be writable
lstrcpy(sz, L"c:\\users\\serge\\desktop\\notepad.dontrun");
CreateProcess(NULL, sz, NULL, NULL, FALSE, 0, NULL, NULL, &info, &pi);
printf("Error = %u\n", GetLastError());
This indeed gives a File not found error (2):
STARTUPINFO info;
ZeroMemory(&info, sizeof(info)); info.cb = sizeof(info);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
CreateProcess(L"c:\\users\\serge\\desktop\\notepad.dontrun",
NULL, NULL, NULL, FALSE, 0, NULL, NULL, &info, &pi);
printf("Error = %u\n", GetLastError());
Note: Tested on Win7 x64
You should create the file as hidden.
CreateFile has an attribute you can use
FILE_ATTRIBUTE_HIDDEN 2 (0x2) The file is hidden. Do not include it in an ordinary directory listing.
Documentation here: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx