Returning an exit code from an MFC based application

Hi,

I'm in the process of writing an MFC-based application that runs commands on a remote UNIX server and routes any standard error text back to the Windows client where it is displayed in a pop-up error dialog. I need to be able to pass command line parameters into the client app which are then used to invoke the command on the server. This all works fine.

The problem I've got is that I need to be able to exit the invoking client application with the same exit code as seen on the server. This is because the client app is invoked by a 3rd party SCM tool and it needs to know whether the command succeeded or not. I originally wrote the client as a console application and this was fine - I simply had to call exit() with the relevant exit code. The problem with that approach is that I got a Console Window popping up when the client app was invoked from the 3rd party tool. This looked quite ugly. By rewriting the application as an MFC project then I obviously don't get the Console Window popping up but I can't return an exit code either!

I don't want to use "start" or any similar mechanism to start the client - I just want to run it from the command line (with all its parameters) and have it exit (say when the InitInstance() function finishes) with the appropriate exit code.

I'm using VC++ 6.0

I guess the questions are:

1) Is this even possible with MFC or do I have to use more low-level function calls?
2) Would it be simpler to write a console app and somehow suppress the console window from appearing? if so - how can I do that?

500 points riding on this one!

Cheers
pgibbsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SteHCommented:
Override ExitInstance of the CWinApp derived class. The return code of this function is the one reported to the shell.
pgibbsAuthor Commented:
SteH,

Thanks for that. However, all my processing is in InitInstance(). As far as I understand it, ExitInstance() is invoked from Run(). Therefore, overriding ExitInstance() doesn't work in this case.

I *may* not open any windows if everything is working so I don't THINK I want to use Run and the normal message pump scenario. Unless you can advise me otherwise!
SteHCommented:
I would guess that ExitInstance is called nevertheless. All per Instance memory allocations need to use ExitInstance for cleanup. This is not needed for a dlg based app but have a try.
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

pgibbsAuthor Commented:
I did - doesn't work! Sorry.
jkrCommented:
Why not just using 'ExitProcess()' and passing the exit code there? I'd also go for the 'ExitInstance()' approach, just save the exit code in a member of your application object and return that from 'ExitInstance()'.
pgibbsAuthor Commented:
I can put ExitProcess() at the end of Initinstance() but that doesn't get passed back to the calling shell.

Basically, when I invoke my client from the command line, the MS-DOS prompt comes back IMMEDIATELY. The application then runs as a normal windows app. However, the exit code (as displayed by %ERRORLEVEL% in the dos window is 0. That's because the windows app has just launched and is still busily running when the prompt returns.

If we stick to our "launching from a DOS window" scenario - what I'd LIKE to happen is the prompt does not return until I call ExitProcess() (or ExitInstance() or exit() or whatever!) Then, when I DO call one of these functions, the exit status is passed back to the invoking shell in the normal way - just as if I'd called exit() from a console-based app.
SteHCommented:
The following works as it returns a value to VS.

int CMyApp::ExitInstance()
{
      // TODO: Add your specialized code here and/or call the base class
      
      CWinApp::ExitInstance(); // do not return value of base class.
    return -15;                          // the value should be stored in a class member.
}

Windows apps don't run in the context of the command prompt. So it will be difficult to get the return type on that command line. Could be easier from another app knowing the process (number) which then waits for the process to end.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
pgibbsAuthor Commented:
Yes - I was thinking about using another app and using something like CreateProcess(). However, if I do that, wouldn't it also have to be an MFC app (to prevent the Console appearing)? And if so, doesn't that just put me back to square one?
SteHCommented:
How do you start your programs at the moment? Not from a command line? If from a command line there is no need to pop up another console. Just the existing one is sufficient.
pgibbsAuthor Commented:
Well, if I rewrite it as a console app then run it from the command line then it just uses the existing console and everything is fine. If, however, I get our 3rd Party SCM tool (which has a GUI interface) to invoke it then a console pops up. That's what I'm trying to get rid of by writing the app in MFC.

At the moment I've rewritten it as a console app with a FreeConsole() call in main(). This means the console flashes up but very briefly. Still annoying but better. However, it would be better still if I could get the invoking application to wait until the process has exited and for it to be able to read the exit status.

Incidently, someone else is asking the same question: Q_20714251. Must be a popular one!
SteHCommented:
MFC apps start in another process so they don't block the other application. Perhaps you have some look with a win32 app which spawns your process and wait for its termination and returning then.
pgibbsAuthor Commented:
Don't win32 apps do the same thing? I've tried /subsystem:windows and /subsystem:console in the link window of VC++ and windows apps (regardless of whether they're win32 or MFC) "return" right away when invoked from the command-line.

I beginning to think that the only viable approach is to write it as a console app but somehow prevent the console window from appearing. I've seen hints around this site (and others) that you can achieve this with #pragma directives to the linker or by changing the default entry point. I've not managed to get this working though - have you any experience of this?
SteHCommented:
No, not at all.
SteHCommented:
No, not at all.
pgibbsAuthor Commented:
Ooops sorry, completely forgot about this. Apologies to all concerned.

I've awarded the points to SteH since I did end up using ExitInstance() but in a different way.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.