A newbie's elementary guide to spawning processes

Gives an elementary introduction to the use of ShellExecute/ShellExecuteEx, CreateProcess, WaitForSingleObject. How to bring up the Find window, the Properties window.

Introduction

Often, we find questions coming from newbies on how to spawn a new process,
how to open a particular document with the program associated with it, how to
launch a web site, how to bring up the mail client's compose window, how to wait
for a program to finish, how to print a file etc. Quite a few of these can be
accomplished using the CreateProcess call. Unfortunately newbies often find that
CreateProcess is not exactly the easiest of calls to understand. But the very
good news for newbies is that you can use some of the shell functions available
through shell32.dll to accomplish the above jobs.

This article is a sort of miniature FAQ that gives you short code snippets
that detail how a particular task can be done. You must look up the functions
discussed here on MSDN. And I'd be glad if people can send in more questions on
similar lines that might fit in here. I also give an ultra brief introduction to
CreateProcess at the end of the article. It is highly insufficient an approach,
but I do think it will serve a newbie as an easy stepping block.

ShellExecute and what it does for you

This function is declared in Shellapi.h which you will need to include. You
will also have to link with Shell32.lib. ShellExecute is one of the API calls
that really saves you a lot of effort. We'll go through the usage of the
function through the mini FAQ format. Look up the function on MSDN to get an
idea of what each of the parameters mean.

Q: How do I start an application under windows?

A: Simple. Just call ShellExecute, passing the full path of the file name you
want to execute.

A: Have no fear, ShellExecute is here. [I hope I am not over-doing this]

ShellExecute(this->m_hWnd,"print",
"c:\\abc.txt","","", SW_HIDE);

Q: I want to bring up the Windows Find window on a particular folder.

A: We use the find verb as the operation parameter and we have
the Windows Find window open up with the directory we have specified. This can
be rather handy if you want to allow users to find some file within some folder.
Just ask them for their folder and pop up a Find Window which has their folder
as the root folder.

ShellExecute(m_hWnd,"find","d:\\nish",
NULL,NULL,SW_SHOW);

Big Brother - ShellExecuteEx

ShellExecuteEx is a more flexible call, in that it allows us to retrieve
information about the program we just spawned. You'll need to fill up the
SHELLEXECUTEINFO structure and pass it's address to ShellExecuteEx. Please
lookup both on your copy of MSDN.

Q: How do I start a program, and halt execution of my current program, till
that program exits?

A: You start the program using ShellExecuteEx and use WaitForSingleObject on
the process handle.

CreateProcess - an ultra brief introduction

The CreateProcess function is part of Kernel32.dll. Windows uses this call to
create a new process and a primary thread for the new process. The primary
thread then starts executing the specified executable. Normally, if this is a
C++ program, execution starts with your WinMain [actually prior to this
the CRT library is loaded and initialized]. For a more comprehensive tutorial on
the use of CreateProcess, I recommend that you read Joseph M Newcomer's article,
An Introduction to Processes: Asynchronous Process Notification.

As you can observe, I am using WaitForSingleObject on the process handle. But
since CreateProcess creates a thread object in addition to the process object, I
might as well have waited on the thread handle as in :-

WaitForSingleObject(ProcessInfo.hThread,INFINITE);

This might cause problems though if, for some reasons, one or more of your
secondary threads are still active even after the main thread finishes. MSDN
says that a process is fully terminated only when all it's threads have ceased
execution. So I recommend that you wait on the process handle rather than on the
thread handle.

Last Updates

Aug 03 2002 - Added tip to bring up the Find window

Aug 03 2002 - Added tip to bring up the Properties window

License

Share

About the Author

Nish Nishant is a Principal Software Architect based out of Columbus, Ohio. He has over 17 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish was a Microsoft Visual C++ MVP between 2002 and 2015.

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored C++/CLI in Action for Manning Publications in 2005, and had previously co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : If you are interested in hiring Nish as a consultant, you can reach him via his google email id voidnish.

In Windows explorer, if I select multiple files and right click->properties, a single dialog box appear with their properties. How can I invoke this using ShellExecute. More specifically, how can i pass an array of files as lpfile.

This may be useful to anyone trying to extend the life of VB6 apps. CreateProcessA (usually used for creating a process and waiting for completion) does not work always in Win 7 and especially Win 8 - UAC causes problems.

Use ShellExecuteEX:

This example is used for executing a program (exe) with or without parameters

This code is cobbled together from this article and others found on the net

I'll leave it up to you to make this a function which returns result codes
.......................................................

Private Type SHELLEXECUTEINFO
cbSize As Long
fMask As Long
hwnd As Long
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As String
nShow As Long
hInstApp As Long
lpIDList As Long
lpClass As String
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hProcess As Long
End Type
Private Declare Function ShellExecuteEx Lib "shell32.dll" (SEI As SHELLEXECUTEINFO) As Long
Public Declare Function WaitForSingleObject Lib "KERNEL32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

That code is not quite right. If I move the dialogue that i kick started abit, my own dialogue does not repaint correctly and it still allows it to take focus. Ideally, I want to spawned process to be like a modal dialog in behaviour.

I am building a small autoexecute for my flash drive using ShelleExecute but I have a problem. One of the applications I am trying to launch is in a different folder, and if its folder is not your current working directory, the program errors out. Even if you try to run it from a DOS prompt, you have to CD to the program's directory first. Is there a way you can pass ShellExecute a working directory, or should I just do something like syste("cd directory")?

Yesterday one of my friend called me and asked me a question and I have no idea

[my study time of VC is no more than 6 days (to him it was 3 days)]

And according to the article you posted, I realized that probably you know the answer

The problem is {How can I get the window handle of the process created using function CreateProcess? (other functions that can accomplish this task is also welcomed)} We are looking forward for the answer!

grin_t wrote:
How can I get the window handle of the process created using function CreateProcess?

Enumerate all the desktop window and compare there execuable path with launch path provided with CreateProcess.. for reteriving the window executable path linked with HWND use <name style="font-weight: bold;">GetWindowModuleFileName

"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow

Specifically, I want to use C++ to generate an Extended Stored Procedure, to be called from a VB6 app, which takes a DOS command as a string input parameter and execute this command.

I want to use this to call the bcp utility to import or export text file data to or from database tables.
Is this possible using ShellExecute?
I've tried to do it using the system() function but with no success.

I can get it to work in an C++ executable but when I try to use it in an extended stored procedure, SQL Server hangs.