Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Running a program from a program

Posted on 1998-08-24
15
Medium Priority
?
241 Views
Last Modified: 2011-09-20
I have an application that minimizes itself and then launches another program with the ShellExecute command.  Is there any way I can find out when the second program is done so I can Restore the main window of the first app?  Please note that I have no access to the second app, so I can't have it send a message back.

Thanks for any help
Bob Z.
0
Comment
Question by:ZeinerRJ
  • 5
  • 5
  • 3
  • +1
15 Comments
 
LVL 8

Accepted Solution

by:
Answers2000 earned 300 total points
ID: 1171104
MFC ? Win32 ?

From codeguru (http://www.codeguru.com)

(begin quote)

This article was contributed by Alan Chen.
This is a dll that exports a function called Wait(). Wait() is similiar with WinExec(). The difference is that Wait()

run an application and return until the application ends.

This project consists of 3 functions:

Wait()
Create a thread and wait for an event. Use pThreadEvent to identify if the called application ends. WaitForSingleObject()

pauses the application and waits for the called application to end.

_declspec(dllexport) BOOL Wait(CString szCmdLine)
{
    LPTHREADINFO pThreadInfo = new THREADINFO;
    CEvent *pThreadEvent = new CEvent(FALSE, TRUE);
    ASSERT_VALID(pThreadEvent);
    if(pThreadInfo)
    {
        pThreadInfo->pTermThreadEvent = pThreadEvent;
        pThreadInfo->strPathName = szCmdLine;

        AfxBeginThread(LaunchAndWait, pThreadInfo);
        WaitForSingleObject(pThreadEvent->m_hObject, INFINITE);
        return TRUE;
    }
    return FALSE;
}

LaunchAndWait()
Call LaunchApplication() to run the application and wait for an event.WaitForMultiObjects() wait for either the called application to end or the main process to end.

UINT LaunchAndWait(LPVOID pParam)
{
    LPTHREADINFO pThreadInfo = (LPTHREADINFO) pParam;
    PROCESS_INFORMATION stProcessInfo;
    if(LaunchApplication(pThreadInfo->strPathName, &stProcessInfo))
    {
        HANDLE hThreads[2];
        hThreads[0] = pThreadInfo->pTermThreadEvent->m_hObject;
        hThreads[1] = stProcessInfo.hProcess;
        DWORD dwIndex = WaitForMultipleObjects(2, hThreads, FALSE, INFINITE);
        CloseHandle(stProcessInfo.hThread);
        CloseHandle(stProcessInfo.hProcess);
        pThreadInfo->pTermThreadEvent->SetEvent();
        if(pThreadInfo)
            delete pThreadInfo;
    }
    else
        pThreadInfo->pTermThreadEvent->SetEvent();
    return 0;
}


LaunchApplication()
Call CreateProcess to run the application.

BOOL LaunchApplication(LPCTSTR pCmdLine, PROCESS_INFORMATION *pProcessInfo)
{
    STARTUPINFO stStartUpInfo;

    memset(&stStartUpInfo, 0, sizeof(STARTUPINFO));

    stStartUpInfo.cb = sizeof(STARTUPINFO);

    stStartUpInfo.dwFlags = STARTF_USESHOWWINDOW;
    stStartUpInfo.wShowWindow = SW_SHOWDEFAULT;

    return CreateProcess(NULL, (LPTSTR)pCmdLine, NULL, NULL, FALSE,
        NORMAL_PRIORITY_CLASS, NULL,
        NULL, &stStartUpInfo, pProcessInfo);
}

(end quote)

I believe there is a bug/feature - this won't work if the 2nd app is 16bit Windows or DOS.

You may also want to hide your app rather than just minimize it, otherwise the user can attempt to restore the app, and will be confused when it doesn't restore (because it won't respond to messages when "waiting").

You may also want to remove the "_declspec(dllexport)"
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1171105
Ignore this comment of mine
--> You may also want to remove the "_declspec(dllexport)"

This is req'd I misread the code.
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1171106
Arghhh!

Read it right first time!!  The _declspec is req'd if you are exporting the function from a DLL.  If you simply embed the code into your app, then you don't need it.  

So the original post was correct, and my 2:04PM comment is rubbish


0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 22

Expert Comment

by:nietod
ID: 1171107
What you need to do is open a handle to the process with OpenProcess() and then wait on that handle with WaitForSingleObject().  When the process termiantes, WaitForSingleObject will return.  (You can do more fancy things if you want your application to "stay alive" while waiting, but that is the general idea.

The problem is that to use OpenProcess() you need the process's ID. Unfortunately you don't have the process's ID, you have its instance handle.  There is no way to convert to the ID that I know of.  I believe that is a security measure.  

To get around this, you could open the process with CreateProcess()  That way you can get the process's ID and use it to open a handle for the proccess.  However, CreateProcess needs the name and path of the executable to be run.  To get around this use FindExecutable().  This finds the executable that ShellExecute() would run for a specified file.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1171108
Answers2000, that's not really what he needs.  The root of the problem is that he doesn't have an executable file name to pass to CreateProcess() (or your procedure) and that ShellExecute() doesn't return the information needed to monitor the process started.
0
 
LVL 11

Expert Comment

by:alexo
ID: 1171109
ZeinerRJ, the answer to your question is ShellExecuteEx().
See the documentation for the SHELLEXECUTEINFO structure.  Especially the hProcess
member.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1171110
Alex is that a handle to the process, as in a the return value of OpenProcess(), or is it the handle to the process's instance, as in the return value of ShellExecute()?  
0
 
LVL 11

Expert Comment

by:alexo
ID: 1171111
The return value of ShellExecute() is totally useless bacause instance handles are only valid in the same address space.  Ergo, first option.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1171112
Right, I understand that.  That is why I thought it was necessary to find the EXE with FindExecurable() and then run it with CreateProcess(), so you can get a process handle.  

My question is:  "is the handle returned by ShellExecuteEx() really a process handle, or is it an instance handle?"  Since ShellExecute() returns an instance handle, then I would be surprised if ShellExecuteEx() returned a process handle instead.  
0
 
LVL 11

Expert Comment

by:alexo
ID: 1171113
Process handle.
0
 

Author Comment

by:ZeinerRJ
ID: 1171114
I thank everyone for their comments.  I should have mentioned that I was given a copy of MSVC 1.5 and am trying to learn some C++ on my own until I can take a class.  (D'Ohh!!!)

However, all the comments are interesting, and will certainly be of use.

Thanks again, and if anyone has any new ideas, let me know.

Bob Z.
0
 
LVL 11

Expert Comment

by:alexo
ID: 1171115
Bob, next time please give us the full information so we can supply *correct* solutions.
My comments regarding ShellExecute() and ShellExecuteEx() are only valid for Win32.  Since MSVC 1.x generates Win16 code, you can only file them for future reference...
0
 

Author Comment

by:ZeinerRJ
ID: 1171116
Sorry Alexo, when I posted, I was concentrating on the problem so much that I failed to give proper background info.  However, all I'm doing with 1.5 is trying to give myself a leg up  for when I'll get to take a class in a month or so.  At that time, I'll be using VC 5, or 6, so all these comments are indeed filed for future use.  You have not wasted your time!

Thanks again.
Bob Z.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1171117
Is this class in programing standard C++ or in windows?  A standard C++ (introductory) class will not cover anything like this.  It won't teach anything specific to windows or any other operating system.
0
 
LVL 11

Expert Comment

by:alexo
ID: 1171118
Todd is right.  Better get familiar with virtual methods, multiple inheritance, operator overloading and other mumbo jumbo...
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

885 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question