Hey guys, is there anyway a C++ program will continue to execute and not pause when I run a program for it?
E.g
I've already got

system("iTunes.exe.lnk");
main();

It calls main after it executes the program, but it is paused until I exit iTunes, is there anyway to let the program continue while iTunes is open?
Thanks

If you use ShellExecuteEx you can run another program as a separate process:

#include <iostream>
#include <string>

#include <windows.h> // required for various Win32 API bits
#include <io.h> // required for _access()
#include <shlobj.h> // required for SHGetSpecialFolderPath
#include <shellapi.h> // required for ShellExecuteEx

// helper functions
std::string GetSpecialFolderPath(int csidl_value);
void RunProgram(std::string path);


int main()
{

	std::cout << "Opening 'My Documents' folder as a separate process..." << std::endl;
	RunProgram(GetSpecialFolderPath(CSIDL_PERSONAL));

	std::cout << "Opening 'Desktop' folder as a separate process..." << std::endl;
	RunProgram(GetSpecialFolderPath(CSIDL_DESKTOPDIRECTORY));

	std::cout << "Running notepad as a separate process..." << std::endl;
	// Try putting the path to a program on your system here:
	RunProgram("C:/WINDOWS/system32/notepad.exe");

	std::cout << "Attempting to run something which doesn't exist..." << std::endl;
	RunProgram("C:/thisdoesntexist.exe");

	std::cout << "\nPress return to continue..."; 
	std::string dummy;
	std::getline(std::cin, dummy);

	return 0;
}

// Get the path to a special system directory using its CSIDL_ value
std::string GetSpecialFolderPath(int csidl_value)
{
	LPSTR rawPath = new CHAR[MAX_PATH];
	SHGetSpecialFolderPath(0, rawPath, csidl_value, 0);
	std::string path(rawPath);
	delete rawPath;
	return path;
}


// Run the program at the passed-in path
void RunProgram(std::string path)
{
	// check the specified path actually exists
	if( _access(path.c_str(), 0) == 0 )
	{
		// it exists, so lets open it
	// first set up some shell execute info for the program/folder/document
		SHELLEXECUTEINFO sei;
		sei.cbSize = sizeof(SHELLEXECUTEINFO);
		sei.fMask = 0;
		sei.hwnd=0;
		sei.lpVerb="open";
		sei.lpFile=path.c_str();  // this is the only bit that we'll change for now
		sei.lpParameters=0;
		sei.nShow=SW_SHOWNORMAL;
		sei.hInstApp=0;
		sei.lpIDList=0;
		sei.lpClass=0;
		sei.hkeyClass=0;
		sei.dwHotKey=0;
		sei.hIcon=0;
		sei.hProcess=0;
		sei.lpDirectory=0;
		
		// finally, let's attempt to run whtaever is at the passed-in
		// path by passing the 'shell execute info' to ShellExecuteEx
		ShellExecuteEx(&sei);
	}
	else
	{
		std::cout << "ERROR: Unable to open \"" << path << "\" !!" << std::endl;
	}
}

The above example uses ShellExecuteEx to open the current users 'desktop' folder and the current users 'my documents' folder before running notepad and then attempting to run something which doesn't exist. These programs are all ran by the system as separate processes, allowing the execution of the calling program (i.e. the above program) to continue as normal.

Obtaining the paths to the 'desktop' and 'my documents' folders is done by passing the GetSpecialFolderPath function the CSIDL value of the folder we want to find the path to. The CSIDL values are all #defined as preprocessor macros.

To see more on CSIDL values take a look at:
http://msdn.microsoft.com/en-us/library/bb762494%28v=VS.85%29.aspx

If you are running Vista or 7 you might want to take a look at the KNOWNFOLDERID's, which are updated versions of the CSIDL values:
http://msdn.microsoft.com/en-us/library/dd378457%28v=VS.85%29.aspx

Running notepad was done simply by passing the path to notepad to the RunProgram function. You could try putting the path to a program on your PC here if you like!

Finally, I've tried opening something which does not exist.
In this case, the call to _access inside the RunProgram function will fail, causing the code in the else to be called and an error message to be displayed instead!

The paths passed into the RunProgram() function can be folders, executables or documents. If you attempt to run/open a document ShellExecuteEx will run whatever program is associated with that file-type. But if a document does not have a program associated with it, I think the call to ShellExecuteEx will just silently fail.


To round up:
Other than allowing your program to continue unhindered, ShellExecuteEx is a far better solution than using system()!

system() really should NOT be used at all. It's non-standard, non-portable and inherently insecure. And I'm not going to go into any further detail on this subject than that. But if you search for system() here on daniweb or in google, you'll almost certainly find lots of posts/articles which will explain why system() is bad!

I really can't be bothered to go over that all over again! I think Daniweb has enough posts about the deficiencies of system() calls!

Anyway, I hope this has helped!
Cheers for now,
Jas.

This article has been dead for over six months. Start a new discussion instead.