I'm making a custom UI at the moment so I'm trying to launch a game from within my C++ application using CreateProcess. Here is my code so far
PROCESS_INFORMATION Processinfo;
STARTUPINFO StartupInfo;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory(&Processinfo, sizeof(Processinfo));
if (CreateProcess(TEXT("C:\\Program Files(x86)\\Steam\\steamapps\\common\\Surgeon Simulator VR Meet The Medic\\Win32\\SurgeonVR.exe"),
GetCommandLineA(),
NULL,
NULL,
false,
CREATE_SUSPENDED,
NULL,
NULL,
&StartupInfo,
&Processinfo))
{
system("pause");
}
Im not quite sure where I'm going wrong as I've never used CreateProcess before, but after looking through a ton of examples I tried to mimic what everyone else was doing to no success.The process isnt being created, and the game is not being launched. Any help is greatly appreciated!
Fixed the issue by using char* path = "C:\Program Files(x86)\Steam\steamapps\common\Surgeon Simulator VR Meet The Medic\Win32\SurgeonVR.exe"; and then using path as a parameter instead. I think the issue was a mistake in the path variable as well as using CREATE_SUSPENDED as a parameter.
Related
I am working on development of simple application launcher program which is supposed to launch from its main window several applications.
One of the applications to launch is an Internet Explorer and it is supposed to be started minimized.
The problem - my code works as intended only if there is no other Internet Explorer instance already running. If there is one, my application launcher starts its Internet Explorer instance in normal (not minimized) window. I am observing this behaviour only with Internet Explorer. If I modify my code to start Notepad instead of the Internet Explorer, then everyting works as intended no matter how many instances of the Notepad are already running - all new Notepad instances start minimized. Here is the relevant part of my code which in fact is very basic:
case IDC_MAIN_BUTTON5:
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWMINIMIZED;
CreateProcess(L"C:\\Program Files\\Internet Explorer\\iexplore.exe",
L"",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);
WaitForInputIdle(pi.hProcess, 1000);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
break;
Any ideas or suggestions how to solve this strange problem would be very much appreciated.
So, curious problem, I'm trying to create a process, and then resume it, mostly exploring the Windows API. I've noticed that if I do this:
system("C:\\Windows\\System32\\calc.exe");
It will open a calculator exe, however if I try to do the same thing using CreateProcessA, I get this:
STARTUPINFO starting_info;
PROCESS_INFORMATION process_info;
// let's try and make a process
if (!CreateProcessA(NULL, "C:\\Windows\\System32\\calc.exe", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &starting_info, &process_info)) {
return;
}
// resume thread
NtResumeThread(process_info.hThread, NULL);
This for some reason throws an error of 0xc0000142 most of the times when it "creates" the process, else it just fails.
What's going on?
See the following MSDN sample code for creating a process:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682512(v=vs.85).aspx
You need to zero out the si and pi structs, also set
si.cb = sizeof(si);
In the end, close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
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);
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))
{
//...
}
i am using visual c++ 2010 i want to learn create processes in c++ can anybody help where find tutorial or does here exist book?
thanks
You can use the below snippet to create process. Just replace the bold part below with the path of the executable which needs to be run.
PROCESS_INFORMATION processInfo; //we get this as an [out] parameter
STARTUPINFO startupInfo; //this is an [in] parameter
memset(&startupInfo,0, sizeof(startupInfo));
memset(&processInfo,0, sizeof(processInfo));
startupInfo.cb = sizeof startupInfo ;
if (CreateProcess("**Executable_Path**", NULL, NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo))
{
// If process is created successfully
WaitForSingleObject(processInfo.hProcess,INFINITE);
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
}
else
{
//Cannot create process.
}
Check Win API CrateProcess function:
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx
Please refer MSDN, the best source for Microsoft related technologies.