Solved

Running a program from a program

Posted on 1998-08-24
15
209 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 100 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
 
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
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 run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

757 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now