Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Keep Alive

Status
Not open for further replies.

MikeFromMountDennis

Technical User
Mar 28, 2016
6
CA
thread184-1255454 has some sample code, but I can't figure out the logic.

When Foxpro loses a network connection, it pretty well always shuts down the application, and sometimes even worse, opens a dialog box and waits forever.

Network interruptions seem to be a fact of life with optimistic sharing. Flock is even worse. MySQL is slowly taking over the actual data storage, but there is no budget for a total port, and it requires configuring each workstation for ODBC, thus not user friendly.

SO other than a table with last cycle datetime, and a second session monitoring, how do you keep a session of a foxpro app running at all times?

My app grants no-update access to shared files, with a single station locking & updating. This resolves issues of sleeping computers, crashed sessions, etc. But how to make that station keep alive?
 
Welcome to the forum.

thread184-1255454: How to restart an application has some sample code, but I can't figure out the logic.

The logic is pretty simple. When the program detects a condition that requires it close down, it first calls a function which re-loads the executable - the same executable that is closing down. It then goes ahead and closes down.

The function calls the Windows ShellExecute() function. The job of that function is to execute a specific program or application (actually, it does a little more than that, but let's keep it simple). So, in effect the program is executing itself.

Because ShellExecute() launches a new instance of the program, the old one (the one that is about to shut down) continues running, and proceeds to execute the Quit command, which is what actually closes it.

As far as the user is concerned, they see something going wrong in their application (or maybe they don't; it depends on what condition is causing the shutdown). Then, a moment or two later, they see the application's start-up screen or login or whatever, so they can carry on with their processing.

I have to say that this is not the way I would do things myself, but it should work perfectly well, and there is no reason for you not to incorporate it directly into your application.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, the function BROWSER() has to go into some PRG file and you have to have some SET PROCEDURE TO that PRG file somewhere to be able to call BROWSER(SYS(16)) from anywhere you want to (Shell)execute your own application, to restart it.

Anyway, that won't restart and place you at the same open forms and loaded data again, it really just restarts the current appilcation again, so you go to the login prompt/start screen. The user just doesn't have to find the entry in the start menu or desktop shortcut, that's all you save with that code.

If you expect something like modern browsers offer, to restart all open tabs and reload all pages, you have to program that yourself.

Bye, Olaf.
 
I would rather consider SYS(16,0) or _VFP.Servername and do this:

Code:
lcThisapp = SYS(16,0) && or _VFP.Servername, whatever suits better
RUN /N "&lcThisapp."
QUIT

Bye, Olaf.
 
SO the issue would be a condition with a dialog trap that shows up during ON ERROR! Easy enough to start an app with a saved environment in Foxpro ( using save to / restore from ) and relaunch from within On ERROR.

Any suggestions on how to disable system messages though? "Press any key to continue" will prevent shellexecute()

I suspect that adding a status server to monitoring last update, and relaunching the app if updates stop, might be simpler that trying to restart. This app has its own status table, so saving environment isn't an issue during an error.

 
> Easy enough to start an app with a saved environment in Foxpro ( using save to / restore from )
Well, you have a very naive idea of how things will get back to where you left them. First of all SAVE TO doesn't save objects, so all forms are still not open. Even considering the bigger picture and other commands restoring the state you left, there is no way to get back buffer states. Why would an executable restart help at all? You don't want to get back to a broken situation.

I know you only talk about unstable network conditions, which might be fixed when you restart, but it's not the first time I say you better act on the real problem instead of trying to work around it. Sonce the only thing you do is restart, the least thing you'd need to add at startup is checking, whether you can read/write on a network share, so the network is back.

The ideal solution would involve saving to local files instead of the network share, to be able to pick up where you left., but that would mean you'd need to reimplement the whole TABLEUPDATE with redirect to local files. No easy job.

You might know CREATE VIEW viewfile and SET VIEW TO viewfile, but do you really have experience with it? In about 20 years of forum answering it wasn't mentioned once, because it's not really recommendable, to be clear: It doesn't restore cursors.

Bye, Olaf.
 
The app in question has NO USER INPUT, all forms and cursors are for display only so the customer can see daily sales, last order processed, web traffic, etc. Passing the app an order number can restore everything since the objects load with a parameter ( the last processed order number ) . Cursors are restored when the objects initialize. Storing memory is already part of the on error routine, as is the open tables and pointers information.

The REAL PROBLEM is 50 year old buildings never built to last, rats chewing cables, water seeping into buried cables, typical urban decay. Way above my pay grade. Also ransomware and streaming video causing timeouts! I just want my tiny piece of the system to not generate phone calls since the server room is usually locked and if my status app stalls, people phone me. If the power goes off, not my problem. Very few installations have working UPS at every station, and Foxpro tends to leave a lot of files locked if Windows optimistic locking is enabled, which seems to be the default.

SO being able to automatically restart an app like a messaging system or status screen is a valuable tool. Don't disagree that a stable network is a good thing to have, just that they are not as common as one might hope.







 
>Passing the app an order number can restore everything

Well, that changes the game quite a bit. Then do that. And in that case you don't RESTORE variables, that way you'd just risc putting them in an invalid state. After recreating whatever display of the order, the variables will be in a new valid state and that may differ, as data may already have changed. You create all variables and their state as needed anyway by creating instances, starting forms, etc.

The point of restoring veriables mainly is for enabling debugging at a line reported to error, to be able to go back there and reproduce the veriables present, when the debugger sits at the poiint of failure and then examine, whether expressions fail and why. But if you start an app, which runs classes etc. based on the order number parameter, all variables will be in place and with current correct values anyway, so no need to restore them, they are restored by executing the code. In the same manner browser also only save the URIs they had and not the DOM and other internal states, they simnply reload pages and the pages display in their current state and not in a saved state.

You also find how to turn off smb2/3 to be able to turn off opportunistic locking, if you don't google optimistic locking, because the latter is a foxpro loocking type and term, which has nothing to do with opportunistic locking.

You now set lcOrdernum= ALLTRIM(ordernumber) and then do [tt]RUN /N "&lcThisapp." &lcOrdernum[/tt] or pass [tt]lcOrdernum[/tt] in ShellExecuite as third parameter or as second parameter of Griffs BROWSER function, ie do [tt]BROWSER(lcThisApp,lcOrdernum)[/tt]. In both cases you need the number as string, in case of using RUN, because otherwise you'd not be able to use macro substitution, and when doing [tt]RUN ... lnOrdernum[/tt] that'll pass the variable name itself instead of its value. In case of BROWSER/ShellExecute the number needs to be turned into a string, because the parameter for the parameter line is a string parameter. If the ordernumber is an alphanumeric string anyway, this can be put as is into lcOrdernum.

Bye, Olaf.
 
Besides all this, the best way to keep a service like app running is making it a real service and having a setting in services to restart that service in case of a crash. It's simply a setting for any service in the service manager in service properties in a tab called recover or similar. You could use Srvany to start your exe as "cargo" of the srvany service. Later I'll be on an English OS, where I can show a screenshot.

Bye, Olaf.

 
Any suggestions on how to disable system messages though? "Press any key to continue" will prevent shellexecute()

If I've understood your posts correctly, "Press any key to continue" is not a system message in this case. The message appears because NySQL detected an error, and your application is not taking any specific steps to handle that error.

I don't know the inner workings of your app. But if, for example, you are using SQLEXEC() to get data from MySQL, then you need to test to see if it returns a negative reply, then use AERROR() to determine the cause of the error, and then act accordingly.

You probably also need to tell MySQL (or, more exactly, the MySQL ODBC driver) not to display its own messages. You do that by setting the connection's DispWarnings property to .F. (see the Help for CURSORSETPROP() for more information).

I'm not saying that you should be doing exactly what I just described. My point is that it is up to you to trap the errors that might cause the "Any key" message, so that the user never sees them.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I'd say he used [tt]Wait[/tt], purely without any parameter. Simply don't use that command this way and you don't have such a state. But any modal state will make QUIT not work. You then need KillProcess. If your app really crashes though, that won't be a problem.

Bye, Olaf.
 
Yes, Olaf, it might well be a WAIT. But the point is the same. You need to get rid of anything that requires the user to take action before you can close down.

I would also use KillProcess in this case. Ther are too many things that can cause a QUIT to fail.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
There is SYS(2335,0), which will cause any modal state, even the ones you might cause unintentionally, into an error, which triggers the error handler, obviously.

Now double check all code in the error handling for not causing any modal state, which woud make your error handler trigger itself, you can QUIT from there, too. And when logging errors you also will see which places in your code may cause modal states.

Server side unattended code shouldn't have any display itself anyway. Load date, process data, store it somewhere any client can grab it, no matter whether in the form of DBFs, txt or other docs. Whatever you do, the server side process shouldn't need any display. You might only have some display to monitor via remote desktop connection, but it shouldn't be the main function of such a process and it should be display output only like ? to _screen or status bar messages via SET MESSAGE TO.

Bye, Olaf.
 
Olaf,

Now you mention it, SYS(2335,0) is a good way to deal with this, provided you use it in conjunction with an error handler that can kill the application without itself going into a modal state.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Yes, that's what I'd propose. Anyway, using KillProcess or TerminateProcess or whatever the API call was, is handling cases, where QUIT isn't hardly enough shutting down the process.

In regard of the Service properties I mentioned earlier, see here:
servicerecovery_bc8aux.png


To run your EXE as SrvAny "cargo" see SrvAny with VFP samples, eg
Bye, Olaf.

PS: It's also good the article mentions SYS(2340). You can easily see from logging off, if the service will keep running without user session or not, but it's good to know how you can keep a process up even though those endsession windows messages come to your exe.
 
Thx, ON ERROR has no waits, but file opening routines do have retry logic with a user warning. I will investigate Sys(2335, 2340 ) opportunities.

BTW, all errors are trapped into an error routine like
* Error psuedo-code
TRY
DO mainblock && saves all error and environment information for debugging, typically triggered by corrupt data from web forms, saved on workstation and emailed to Administrator
CATCH TO oErr

*!* strtofile function to record all oErr properties on local hard drive but not emailed since an error in error-trapping usually means there is a serious non-Foxpro error condition

FINALLY
CLEAR EVENTS
ENDTRY



I will investigate sys(2340)
 
Well, try..catch is not what I'd call error routine, the term coined for it is Structured Error Handling. It is not inferior to ON ERROR general error handling, but also not superior. You do wrong, for exampe, if your main.prg has one TRY/CATCH around the block of code, because any error in called routine also is trapped in a CATCH of such a construct out of the context of the error.

You can only handle object errors with the object reference in scope in the objects Error event, so structured error handling should just be used for rather small snippets of code with one or two expected exceptions, eg in code handling files you can expect drive outages, file not found/moved, access privilege problems, and so you could put file I/O in TRA/CATCH.

SYS(2335) can help you turn anything into an error, that you won't want to cause a modal state. That can also be a USE in the case of the error you mainly mentioned; Network outages or opportunistic lock problems (though they are no lock and any additional access should break them instead of getting no access). Because a USE failing causes a file open dialog. To suppress that SET TABLEPROMPT OFF.

That means SYS(2335,0) helps you, no matter, if you don't turn your EXE to be the cargo of a SRVANY service or not. SYS(2340) might help you, only if you go the SRVANY route. Calvin Hsia says this is needed for old OS or old SRVANY versions. Both should not be the case, but as I said you can easily check, whether your process survives a logoff or not. Call a routine in ON SHUTDOWN simply logging the datetime of shutdown.

Bye, Olaf.
 
You should not put TRY / CATCH / ENDTRY (structured error handling) in an error routine called by ON ERROR. Structured error handling is an alternative to ON ERROR. The two don't go together in the way you are doing.

Also, you shouldn't end an error routine with CLEAR EVENTS. If an error has been generated, your environment will be unstable. Things will have gone wrong, and you won't know what those things are. Tables might have failed to open; variables might contain the wrong data type; functions might not have been executed.

In those circumstances, you need to close your application as quickly as possible. CLEAR EVENTS doesn't do that. It merely transfers control to the line of code after your READ EVENTS. Your program will probably then perform further processing (such as releasing objects or closing forms), even though the error condition is still present. And that processing might in turn generate a wait state or another error.

Even QUIT has problems in these circumstances. QUIT will close any open forms; these forms might have code in their Destroy or Unload events that neeed to be executed. Again, this will happen even though the error condition is still in force.

That's why we have suggested an API call as a way to terminate the appplication. I use ExitProcess() to do this, as follows:

Code:
* Right at the end of the error routine
DECLARE Integer ExitProcess IN WIN32API 
ExitProcess()

Of course, in most applications you would only do that after you have safeguarded the user's data (by reverting all buffers and rolling back all transactions). But that's not an issue in your case, as the application is read-only.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top