How do I open an .exe from another C++ .exe? - c++

What I want to do is open an .exe from another .exe. I really don't know how to do this, so I searched the internet. I tried some suggested methods from the internet, but it didn't work.
Here's my code:
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
system ("OpenFile.exe");
system ("pause");
return 0;
}
When I run it in DEV C++, it compiles, but I get a error. Can someone please help me?

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. If that doesn't scare you silly, check your pulse.
Anti virus programs hate it, your program could get flagged as a virus.
You should use CreateProcess().
You can use Createprocess() to just start up an .exe and creating a new process for it.
The application will run independent from the calling application.
Here's an example I used in one of my projects:
#include <windows.h>
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 (removed extra parentheses)
);
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
EDIT: The error you are getting is because you need to specify the path of the .exe file not just the name. Openfile.exe probably doesn't exist.

I've had great success with this:
#include <iostream>
#include <windows.h>
int main() {
ShellExecute(NULL, "open", "path\\to\\file.exe", NULL, NULL, SW_SHOWDEFAULT);
}
If you're interested, the full documentation is here:
http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx.

Try this:
#include <windows.h>
int main ()
{
system ("start notepad.exe") // As an example. Change [notepad] to any executable file //
return 0 ;
}

You are getting this error because you are not giving full path. (C:\Users...\file.exe)
If you want to remove this error then either give full path or copy that application (you want to open) to the folder where your project(.exe) is present/saved.
#include <windows.h>
using namespace std;
int main()
{
system ("start C:\\Users\\Folder\\chrome.exe https://www.stackoverflow.com"); //for opening stackoverflow through google chrome , if chorme.exe is in that folder..
return 0;
}

When executable path has whitespace in system, call
#include<iostream>
using namespace std;
int main()
{
system("explorer C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe ");
system("pause");
return 0;
}

Provide the full path of the file openfile.exe
and remember not to put forward slash / in the path such as
c:/users/username/etc....
instead of that use
c:\\Users\\username\etc
(for windows)
May be this will help you.

I know this is a bit late but this is to help all the new the c++ devs.
Basically I found that if you set the file path to the location then call the program you can bypass the error.
cout << "Opening Firefox";
system("cd C:\\Program Files\\Mozilla Firefox");
Sleep(1000);
system("start firefox.exe -P");
As you can see I set the file path to the location of Firefox then launch it. In my case I'm launching the Profile manager of Firefox, if you want to launch just Firefox remove the -P. I also put in a Sleep() to give my computer time to switch file paths. if you want to go back to the default file path use, system(cd C:\\Windows\\System32);. I made this by replicating commands in the command line for windows, though you would use Linux specific commands + file paths if that is what you are using.

Related

Open a few files, wait ~30 mins, relaunch them in C++

I posted a thread about how to do this in batch but it turns out batch scripting isn't very popular and I barely even know it so now I'm asking for your help doing this in C++.
here's what I tried
#include <Windows.h>
using namespace std;
void openBat(char* path) {
system(path);
}
int main() {
for(;;) {
openBat("C:\\Users\\Ivan\\Desktop\\folder\\run.bat");
Sleep(1800000);
//kill opened process
}
return 0;
}
I'm not sure how to kill the opened process because every time I run the bat script it will have a new ID and I can't kill by name because I need to have 4 of these open. All help is appreciated.
What you're doing there isn't really C++. You're basically using windows to interprete the commands you pass it like batch would do. Here is what you want to do in C++, even if it only runs on Windows.
#include <Windows.h>
#include <string>
std::wstring GetEnvString()
{
wchar_t* env = GetEnvironmentStrings();
std::wstring result{ env };
FreeEnvironmentStrings(env);
result.push_back('\0');
return result;
}
int main()
{
//Setup needed structures
STARTUPINFO si{ sizeof si };
PROCESS_INFORMATION pi;
//Command line (read- and writeable)
wchar_t cmd[] = L"cmd.exe /C C:\\Users\\Ivan\\Desktop\\folder\\run.bat";
//Create process
CreateProcess(nullptr, cmd, nullptr, nullptr, false, CREATE_UNICODE_ENVIRONMENT,
const_cast<wchar_t*>(GetEnvString().c_str()), nullptr, &si, &pi);
Sleep(1800000);
//Process Termination
TerminateProcess(pi.hProcess, 0);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
I'd recommend you read up on the CreateProcess function, as well as the Terminate Process one. There is also an example from Microsoft about how to use the former of the two. I hope this information can help you.
edit: Fixed stuff. Should work now. Credits to user4581301, his links were really useful.
I think the solution can be killing the self process tree without killing process itself.
Terminate a process tree (C for Windows)
When you create a process, hold onto the process handle and use the handle to terminate the when you are done. With the handle you know exactly which of possibly thousands of instances of the same process you want dead.
Note: Terminating a process may have undesirable results. You are almost always better off writing the processes in such a way that you can message them and request that they terminate themselves politely. How you would do this with a batch file... Smurfed if I know. Someone else may have a waaaaay better answer to this problem, and I'm fine with that. One day I might need that better solution.
On Windows you likely want CreateProcess and TerminateProcess.
Running a batchfile with CreateProcess is covered here: Use CreateProcess to Run a Batch File
Terminating a process launched with Create process is covered here:
how to terminate a process created by CreateProcess()?

How to to open a program with CreateProcess if only its name is known?

Like in the following example I'm trying to start Googles Chrome browser from a Windows application using the Windows API function CreateProcess.
The problem I have is that I dont know the path to the Chrome application (or any other application in the Program path). How can I get this?
In the code below I commented three different examples. In case I start "calc", the Calculator is started as it is in the Windows/System32 path. In case I start Chrome with the full path to the application it runs too. But if I omit the path and just try to start "chrome" I get an error #2.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain()
{
char* cmd = "calc"; // works... calc.exe is in windows/system32
// char* cmd = "chrome"; // doesn't work... how can I add the path if it's not known (e.g. windows installed on D:\)
// char* cmd = "c:/program files (x86)/google/chrome/application/chrome"; // works (even without extension .exe)
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)
cmd, // 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);
}
Note: if I enter "chrome" (without the quotes) in the Windows Run command window, Chrome starts too. What I'm looking for is the same functionality. However, my application can reside anywhere and is not necessarily located on the same drive as Chrome.
If you really must use CreateProcess then you will need to find out where it is installed and pass the full path to the executable. That's going to require some registry hacking.
However, I feel that there is an easier and more robust way. Chrome registers itself in the AppPaths registry so ShellExecuteEx with the file specified as L"chrome" and the default verb will do the job.
This is likely to be unrelated to WinAPI and the CreateProcess function, but only to the environment variable PATH. By default, it contains the path for all standard windows commands like calc or notepad, but you must add the path for other commands that you add later, be it under Program Files or anywhere else.
What to do:
carefully note the actual path of chrome
open Control Panel / System / Advanced system parameters
click Environment variables: you will find a PATH (case does not matter) in user and system variables.
add the path for chrome on one (system is meant meant for all users)
It should now be possible to launch chrome without specifying its full path.
NB: unsure for the actual labels for all of the above, my own box speaks french...

how to launch dx app using createProcess()

using this code snippet:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
char szExe[] = "C:\\Apps\\Desktop\\Release\\simplesample.exe";
//char szExe[] = "C:\\Windows\\System32\\notepad.exe";
if(CreateProcess(0, szExe, 0, 0, 0, 0, 0, 0, &si, &pi))
{
// optionally wait for process to finish
WaitForSingleObject(pi.hThread, 0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
when I use notepad.exe, notepad gets launched.
However, when I use the path to simplesample.exe, it launches simplesample and crashes immediately. I fail to understand why simplesample won't launch properly from createProcess.
I can launch simplesample.exe from command prompt as is.
PS: Simplesample is a dx sample app using winmain
Ty to pass directory where simplesample.exe is to lpCurrentDirectory parameter of CreateProcess(). Probably, this program searches for assets, shaders or DLLs in current folder, but receives directory of calling process and thus it cannot find them.
From docs:
lpCurrentDirectory [in, optional]
The full path to the current directory for the process. The string can also specify a UNC path.
If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature is
provided primarily for shells that need to start an application and
specify its initial drive and working directory.)

Trying to use CreateProcess() ; no compiler errors but main keeps crashing

I'm trying to create a function which opens a PDF in firefox separate from the main process. I believe I am having trouble with the parameters for createProcess... any help is greatly appreciated
EDIT: the batch file is being created, I have tested it several times, and to explain a bit:
The batch file is because I really don't know what I am doing, I am a student in computer science and this is a side project to help me at my job. I work at a law office and file the mail electronically as it comes in. I wanted to make a simple program that would loop through the scans directory, display the scan and prompt the user for information about the document. Therefore I need to be able to build a file path dynamically. Originally I was using "system" to open firefox and display the document. After a bit of trying I got it to work with a batch file. I then learned that system is a blocking command and that I would need to start a separate thread. This is where I ran into createprocess. I simply continued to use the batch file from my old system idea... And the more I think about it I can't remember which professor suggested the batch file or why...
void openPDF(char scansQueue[][MAX_NAME], int index)
{
// build bat file
fstream outfile;
outfile.open("C:\\firefox.bat");
if(outfile.good())cout<<"outfile good!!!!"<<endl;
outfile<<"\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\" \"C:\\Scans\\" <<scansQueue[index]<<"\"";
STARTUPINFOW si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if(!CreateProcess(NULL, L"C:\\firefox", NULL, NULL, false, 0, NULL, NULL, &si, &pi))cout<<"PROCESS FAILED TO EXECUTE!!!";
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
There are several problems with this code. A few has already been pointed out in the comments (closing potentially invalid handles on failure, possibility that the batch file can't be created, and the rather questionable command line). Here's a few more issues.
First, you can't run a batch file this way.
The documentation for CreateProcess clearly states:
To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.
Second, you are passing a string literal for lpCommandLine, something that's also explicitly outlawed by the documentation:
lpCommandLine [in, out, optional]
...
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.
Finally, why are you creating a temporary batch file to run a single command? You could easily have written the CreateProcess call to start Firefox directly.

Trouble restarting exe

I need to restart the program that im working on after an update has been downloaded except im running into some issues.
If i use CreateProcess nothing happens, if i use ShellExecute i get an 0xC0150002 error and if i use ShellExecute with the command "runas" it works fine. I can start the command prompt fine using CreateProcess and ShellExecute just not the same exe again and dont want to use runas as this will elevate the exe.
Any Ideas?
Windows 7, visual studio 2008 c++
alt text http://lodle.net/shell_error.jpg
CreateProcess:
char exePath[255];
GetModuleFileName(NULL, exePath, 255);
size_t exePathLen = strlen(exePath);
for (size_t x=exePathLen; x>0; x--)
{
if (exePath[x] == '\\')
break;
else
exePath[x] = '\0';
}
char name[255];
GetModuleFileName(NULL, name, 255);
PROCESS_INFORMATION ProcInfo = {0};
STARTUPINFO StartupInfo = {0};
BOOL res = CreateProcess(name, "-wait", NULL, NULL, false, 0, NULL, exePath, &StartupInfo, &ProcInfo );
ShellExecute:
char exePath[255];
GetModuleFileName(NULL, exePath, 255);
size_t exePathLen = strlen(exePath);
for (size_t x=exePathLen; x>0; x--)
{
if (exePath[x] == '\\')
break;
else
exePath[x] = '\0';
}
char name[255];
GetModuleFileName(NULL, name, 255);
INT_PTR r = (INT_PTR)ShellExecute(NULL, "runas", name, "-wait", exePath, SW_SHOW);
CreateProcess() is an arcane beast. I remember unfondly my first frustrations with it. You should look at the Microsoft CreateProcess Example and the CreateProcess Page. (those links likely have a short lifetime, Googling CreateProcess should work just as well).
I can see 3 problems in your code.
StartupInfo must have "cb" set to the structure size:
STARTUPINFO StartupInfo = {0};
StartupInfo.cb = sizeof(StartupInfo);
The second argument requires both the command and the arguments to form the command line. Your program will see "-wait" as argv[0] and ignore it or pay it no mind.
char command[512];
sprintf(command, "%s -wait", name);
BOOL res = CreateProcess(name, command, // and as you had before
You don't look at GetLastError() if CreateProcess() fails (by returning a zero). It may have helped you but I suspect it would just say "invalid argument" or somesuch. Hey, there's only 10 of them to check, don't be lazy :-)
Another bug I committed is not closing the hProcess and/or hThread handles return in PROCESS_INFORMATION when I was done. I did do hProcess, but not hThread.
Looks like a manifest or registry question judging from the error code. If you can't get the actual error message string for more details, you might try:
moving every possible manifest file (Microsoft.VC80.CRT.manifest and the like) into your exe's directory, to ensure accessibility
cleanly and completely uninstall/wipe out old versions of DLL you may have installer newer versions of (I suggest: uninstall EVERY version, clean the registry with a sweep-clean tool such as Norton's, reinstall the new stuff from scratch)
What happens if you run the process using system()? It gives you less control, but you'll be running it from the same context you're running in. Also, Try monitoring the launch of your second process using ProcMon, it might give you the hint you need about the source of the failure.
Ok worked it all out in the end.
The first time my exe ran it used the default paths and as such loaded vld (a leak detector dll) from the default path. However in the exe i modified the dll path to be the bin folder ([app]\bin) when i restarted the exe using CreateProcess it picked up on a different vld dll (this was my mistake) that had incorrect side by side linkage and it was only after looking at event viewer that i worked it out.
Thanks for all your help.