"Unbreakable" Objects (Part I)

Version: 1.00.01 - last update: Saturday, September 26, 2009, 16:30:00

Previous ChapterNeat Solutions Home (TOC)Next Chapter
This is about how to create a CLEAR ALL resistant class to speed-up things while developing.

Intro

We all use those cool VFP Power-Tools while running our daily business. Most of us have written their own development add-ons from simple menu extensions up to complex wizards and builders and still doing so today. All of these little big helpers suffer from one VFP-typical development environment "disease" called CLEAR ALL. While working with your classes, how often you do you mess up your entire VFP environment you set up so carefully just before? Testing some pre-alpha code fragments all too often leads into situations you’ll only be able to escape from by resetting the entire IDE. Typing in a CLEAR ALL into the command window definitely is a pretty “nice shot” in such a situation but doing so you'll kill them all: those who misbehave and the well-behaved! Okay, “No big deal” you might think “I can restart all my tools by calling some launcher I wrote just for this”. But wouldn’t it be nice (or wouldn’t it be much better) to have some native VFP feature to do that for you automatically? Think about the vantages! This is the solution and fortunately it is easier to implement than one might think:

Let’s use a VFP Form to make it “unbreakable”. After all, I know that it has to be a “DO FORM” to achieve our goal! 
Then remember one of the old-fashioned VFP system variables called “_SHELL”. This is what VFP’s help has on file about it:

The _SHELL system memory variable is used to prevent access to the Command window while a program is running in Visual FoxPro. The DO command with the name of a program to execute is usually stored to _SHELL.You can also specify a command to execute when Visual FoxPro is started by placing the SHELL configuration item in your Visual FoxPro configuration file.The following example demonstrates how _SHELL typically can be used.

  1. A startup program named Mystart.prg is used to launch another program named Myapp.prg. Mystart.prg stores the command to run Myapp.prg to _SHELL. This starts Myapp.prg. Before Visual FoxPro displays the Command window, _SHELL is checked for a command. If _SHELL contains a command, it is executed and Visual FoxPro then stores the empty string to _SHELL.
  2. After the initialization code in Myapp.prg is successfully executed, the command to launch Myapp.prg is stored again to _SHELL. Visual FoxPro does not execute the command or store the empty string to _SHELL, and access to the Command window is prevented. (The Command window cannot be accessed when _SHELL contains anything but the empty string).
  3. Before Myapp.prg finishes execution, it stores the empty string to _SHELL to restore access to the Command window.

Hm, sorry, IMHO this is a very good example of a very poor example :-) Anyway, the bottom line still tells the truth. As long as we store any valid VFP command to the _SHELL system variable VFP will execute it BEFORE passing back interactive control to us. Let’s check that out and type the following into VFP’s command window: _SHELL = "?'HELLO'" next hit Enter and you’ll get a HELLO echoed to the screen.
Next let’s have a look at some of the undocumented VFP functions. There are lots of them lurking around under VFP’s hood as you can read here.
One undocumented SYS() function that can help us master our challenge is named SYS(988). Aside from the fact that nobody knows exactly what the hack it really does internally, this function only returns the Boolean values TRUE and FALSE when called like ?SYS(988). Another way to call this function is SYS(988,.T.) or SYS(988,.F.). This will set the return value to TRUE or FALSE (Lo and behold!). When starting VFP the initial return value of SYS(988) is FALSE.
The really cool thing is that VFP's memory SYS(988) gets it's value from (and stores it to) is absolutely CLEAR ALL resistant. In other words: if we set the value to TRUE no CLEAR ALL resets it to FALSE again until we explicitly call SYS(988,.F.). There is another function called SYS(989) which behaves in almost the same manner. It works with integer values 0 and 1 internally (0 is the boot default).

Some additional words about undocumented functions

SYS(988), SYS(989) whatever we intend to use, we have to be aware that we cannot be sure what will happen! I mean, there is a documented function SYS(987) which helps us controlling how Unicode data is mapped to ANSI. Maybe the undocumented functions we are going to use are doing something comparable?! We do not know! Thus, all you are doing with undocumented functions, you will do it on your own risk!!!
With these little helpers we now can create all kinds of unbreakable development tools! This is our list of ingredients:

  1. Creating a VFP FORM class
  2. Knowing about the VFP _SHELL command
  3. Using some mystique SYS() functions
  4. Knowing about a handful of VFP's form events and properties
Let’s go: First we create a form that only can be killed shutting down FoxPro. Nothing easier than that! Open your VFP command window and type in the following commands:
CD HOME() && do not skip this command!
MODIFY FORM (HOME()+”RESI.SCX”) METHOD destroy
Next add this code into the open method editor window:
_SHELL = "DO FORM HOME()+'RESI.SCX'"
Save your form and DO it. And for now (finally) try to get rid of it WITHOUT busting your current VFP session :-)
The first comment showing a native VFP way to achieve that wins a holiday here in Germany (all inclusive!) « I’ll tell you what that means later ;-)

Previous ChapterNeat Solutions Home (TOC)Next Chapter

1 comment:

  1. Trivial, sorry. To get rid of the form, run this code e.g. select & execute in the command window as a block, not as separate commands:

    _vfp.Forms(1).release
    _shell = ''

    Of course this assumes that form is the only one running, but that's not a problem nor the point :-)

    ReplyDelete