Unbreakable Tool-Forms

Topics: Enhancement Request, General
Sep 19, 2009 at 9:11 PM

Hi everybody,

first let me say to all developers: you've done very good work so far! (I'm using PEM-editor 4 almost daily).

Some of the VFPX tools are using a restart technique after a CLEAR ALL was typed in. They are writing some restart command to VFP's _SHELL variable. I have written about how to do that in my blog a long time ago. Unfortunately VFP's _SHELL is a common/public resource. Thus, after a CLEAR ALL only the luckiest (the last) tool that writes to the _SHELL will survive by restarting itself.

This is no longer an issue!
Finally I found the solution how to create bulletproof CLEAR ALL resident VFP Forms!
And, it is so damn SIMPLE !!!

1.) Your form must be instantiated (with DO FORM) from a SCX-based form.
2.) You might utilize the DO FORM <form_name> NAME <Variable_name> syntax, but not the LINKED command extension!
3.) In your form’s QueryUnload event add the following code:
IF NOT THISFORM.ReleaseType = 2 && close VFP
    CANCEL
ENDIF

That’s all folks! Did I mention that it will be simple? :-))

I would really like to see every VFPX tools creator to implement this tree-liner in their next version!
If you are interested in how I found it out, read my blog:
http://myvfpblog.blogspot.com/2009/09/unbreakable-objects-revisited-final.html

Cheers!
    Burkhard

Coordinator
Sep 21, 2009 at 10:59 PM

Burkhard --

I certainly agree with you that there should be a standard method for handling CLEAR ALL that is used across all VFPx tools.

However, I don't think your suggestion works.  That is, at least, I have found cases where it fails.  (I got intrigued by your call to "Cancel" -- that did not seem right to me.)

To see it fail, I created two forms, A and B, and put your code for QueryUnload in B.  Then I did

Do Form A

Do Form B

Do Form A

Do Form B

Do Form A

When I then did a "clear all", only the first form A closed.  I assume that your 'cancel' killed the entire sequence, so that the the QueryUnloads in subsequent forms were never executed.

For what it's worth, I have supplied my own attempt at standardization after 'Clear All' in PEM Editor, which uses a PRG I wrote, based on your initial blog along with my own additions.  Having noted the issue that you mentioned, that only the last app to write to _Shell gets re-created, ReStartAfterClearAll.PRG, included in the PEM Editor download, handles the problem by writing all requests out to a temporary file which is executed.  It is designed to handle multiple such requests.

Here's the code from PEM Editor's "Clear All".  Note that all the code is just there to set up the call to RestartAfterClearAll, which does the appropriate verification that 'Clear All' has been invoked.

If This.lRestartAfterClearAll
    Local lcEditPropertyCode, lcAppPath
    lcAppPath = Thisform.cApplicationPath + 'PEMEditor.app'
    * Create text that would be used to re-open PEMEditor after Clear All
    TEXT to lcEditPropertyCode noshow textmerge
        Try
        Release _oPEMEditor
        Public _oPEMEditor
        _oPEMEditor = NEWOBJECT('EditPropertyDialog', 'Source\EditProperty.vcx', '<<lcAppPath>>', .F., '' )
        _oPEMEditor.SHOW()
        Catch
        EndTry
    ENDTEXT
    RestartAfterClearAll (This, lcEditPropertyCode)
Endif

 

Sep 22, 2009 at 5:35 PM
Edited Sep 22, 2009 at 9:47 PM

Hi Jim,

many thanks for this very valuable input! I must admit, I wasn’t precise enough with what I wrote the first time! Sure, you are right with what you wrote! But, IMHO, what you observed is nothing to complain about, but the most welcome feature of all! :-) To be more precise now, let me recapitulate:

ANY FORM instantiated using DO FORM ( I’m going to call them DOFORM from now on) that is CANCLEling the QueryUnload event keeps all following FORMS stay alive, too. Isn’t that absolutely great? With “Following FORMS” I mean all FORMS in _SCREEN.FORM[x] collection with a lower index value than the cancelling DOFORM.

I don’t see any problem in that, coz if you really do want your DOFORMS to be destroyed after a CLEAR ALL, then you have to run them solely like this:

DO MyForm NAME  (SYS(2015)) LINKED (as I described it in my blog).
All FORM instances created using CREATEOBJECT() will be destroyed in any event.
If you type CLEAR ALL + RELEASE ALL in the command window all those DOFORMS and FORMS are gone!

There are some things I’ve learned while experimenting with CLEAR ALL and QueryUnload-Cancelling:

1st: CANCELling a form’s QueryUnload() that was caused by a global CLEAR ALL isn’t scoped to that single instance but applies to all following forms in _SCREEN.Forms[n] collection (the rest of the sequence)!
2nd: VFP’s destruction sequence of FORM instances isn’t at random, but loops through the _Screen.Forms[] collection as if one would write:
FOR lnLoop = _SCREEN.FormCount TO 1 STEP -1
          _SCREEN.Forms[m.lnLoop].Release()
NEXT

The first FORM or DOFORM that got instantiated is be placed at the top of the _SCREEN.FORMS[] collection. This makes my finding even more useful (IMHO)
I’ve just started a “long term test” of my new Global Resource Manager (GRM). One part of that project is a so-called ClearAll-Blocker.
When my VFP IDE starts up, the first DOFORM that get’s instantiated is the ClearAll-Blocker (of course it has a CANCEL in its QueryUnload:-). Thus, I can be sure my blocker has the top-position in VFP’s _SCREEN.Forms[]. In other words:
When my Blocker’s DOFORM instance stored in _SCREEN.Forms[_Screen.FormCount] CANCELs the QueryUnload event, all other DOFORMS stay alive. Now, tools like VFP’s Toolbox and all my Class-Browser instances (even your PEM Editor :-) are protected against any CLEAR ALL. That’s a super nice feature I was looking for for a long time!!  Best of all is, I don’t have to alter any tool source code. All VFP tools gain protection against at least a CLEAR ALL. I hope that there are no side-effects! If I will encounter any, I will report them ASAP!

After all, we must not forget that we are running within VFP’s IDE! Thus, the crucial question cannot be “What happens to those spare forms that stay open after a CLEAR ALL instead of getting destroyed”. You can close them with a simple mouse click, don’t you? The crucial question should read: “Do you like to reopen all your VFP tools after a CLEAR ALL manually? Or, if there’s no other option, do you like to patch every tool class with your additional restart code?” As I’m a very lazy programmer, my answer always would have been: “Rats! There must be a third option!” :-)

Coz I need absolute control over my VFP development environment (sometimes I need to suspend QueryUnload-Cancelling while running some special test cases), I enhanced my ClearAll-Blocker. I put some _SHELL restart code in there – and  only there! (BTW: My restart code is far away from being so elaborated like yours, but it hasn't to be at all!) Then I added a checkbox on the GRM DOFORM to switch between enabled and disabled QueryUnload-Cancelling. In case of disabled QueryUnload-Cancelling, I run my restart code. This brings some real advantages: I only have one unique implementation spot. I don’t have to visit all my tools if I want to update/alter restart behavior. I don’t even have to touch any other tool implementation at all!

Again, this all leads me to only one final conclusion:
We need a VFPX Resource-Manager, a central app that is unbreakable, that we can call in such scenarios and others! I am already working on this!
IMHO, it is short-sighted to (re-)implement write access to global resources within each app we build again and again! No matter if you are utilizing OOP or not! A global resource is a unique something and it should be handled/protected/read/write by another unique something/object! What do you think: Why we must open the Windows clipboard before we can gain low level access to it and have to close it afterwards? Why do we have to LOCK records in a multi-user environment? Okay, I’m wandering from the subject :-)

I think we can assert there are two developer groups – one called the “CLEAR ALL fan group” the other the “CLEAR ALL hater” :-)
ClearAll fans are spare; members of that group want to run their DOFORMS typing a simple DO FORM xyz (as always/usual) and want their forms get destroyed by any CLEAR ALL. And, maybe, some of them are complaining about VFP project manager instances do no vanish when they type in a CLEAR ALL ;-)) They belong to some kind of “minority resort” ! I believe that the majority of all VFP developers (like me) would like to have some kind of a ClearAll resistant environment, where they can fully control which tools (DOFORMS) should go after a CLEAR ALL/RELEASE ALL and which of them should stay. What do you think?

Anyway, Jim, you gave me valuable input. I now consider implementing some additional registration mechanism. One should be able to call my GRM then to register one’s DOFORM instance as “volatile”. Before cancelling QueryUnload my GRM then raises an internal timer that kicks my own FORM destruction routine after some milliseconds, looping through my list of registered “volatile FORMs” releasing them.

Coordinator
Sep 22, 2009 at 11:54 PM

Hi Burkhard --

You asked for my opinion, but I think that I'm the wrong person to ask.  I don't have any problems with 'Clear All', and I am accustomed to my IDE as it is.  The only reason that this issue is addressed in PEM Editor is that it was asked for, but I don't use the feature myself.

I'd be more than a little concerned about your use of 'Cancel'.  Do you know what is being cancelled?  Is it merely the process of closing forms, or does it close the remaining part of 'clear all'.  I think you'd have to investigate that thoroughly before getting much farther with your solution.

Cheers,

Jim Nelson

 

Sep 23, 2009 at 4:00 AM

Hi Jim,

thank you for your immediate answer!

You are absolutely right, I will investigate that issue thoroughly before getting much farther with my solution!

The best thing to do (IMHO) is to let it co-exist within my daily VFP development environment (side by side with all the other tools I’m using - like your PEM Editor).
I’m doing enough “strange” things during my daily development business to stress-test what I’m believing  that I’ve found.

I will do a CLEAR ALL irregularly  during my daily work, next I will collect VFP’s IDE environment state comprehensively. Immediately after that I will do a second CLEAR ALL after having disabled my ClearAll-Blocker. Finally I will gather VFP’s environment state again to compare it against the first set. What if both sets are identical (apart from the forms not being released during the first run)?

Thank you for your instant replies, Jim, you’ve been a great help!

Every now and then I need someone that gets me back down on earth :-)

Keep your chin up!

   Burkhard

Von: jimrnelson [mailto:notifications@codeplex.com]
Gesendet: Mittwoch, 23. September 2009 01:54
An: burkhard.stiller@freenet.d
e
Betreff: Re: Unbreakable Tool-Forms [VFPX:69491]

From: jimrnelson

Hi Burkhard --

You asked for my opinion, but I think that I'm the wrong person to ask. I don't have any problems with 'Clear All', and I am accustomed to my IDE as it is. The only reason that this issue is addressed in PEM Editor is that it was asked for, but I don't use the feature myself.

I'd be more than a little concerned about your use of 'Cancel'. Do you know what is being cancelled? Is it merely the process of closing forms, or does it close the remaining part of 'clear all'. I think you'd have to investigate that thoroughly before getting much farther with your solution.

Cheers,

Jim Nelson

Read the full discussion online.

To add a post to this discussion, reply to this email (VFPX@discussions.codeplex.com)

To start a new discussion for this project, email VFPX@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Coordinator
Sep 23, 2009 at 3:14 PM

Hi Burkhard --

Do you really know how to compare the entire VFP IDE environment?  There are lots of things that are CLEARed when you do 'clear all', including DLLs and other stuff.  You sure you can check that all of that is cleared properly (I wouldn't be able to).

Cheers,

Jim

Sep 24, 2009 at 12:08 AM

Hi Jim,

>>Do you really know how to compare the entire VFP IDE environment?<<
To be honest, no – I don’t – not at the moment :-) But I read VFP’s online help about CLEAR ALL. IMHO, this cannot be that big issue. Anyway, I will take a very relaxed approach:-) I will concentrate on memory leak checking. And when my ClearAll Blocker doesn’t make any serious leaks I let him startup and run for the next weeks – just in the background.

>>There are lots of things that are CLEARed when you do 'clear all', including DLLs and other stuff.<<
And most of those things I don’t want to get CLEARed at all :-) Most of the time when I’m doing a CLEAR ALL, I only want to get rid of some temporary vars and sometimes some dangling refs (Ya know, when class browser refuses to open some class def after a test run). This must work furthermore. And if it does with active ClearAll Blocker enabled, why not utilizing this trick ?

>>You sure you can check that all of that is cleared properly (I wouldn't be able to).<<
Well, Jim, I have used countless VFP tools in the past – some of them really corrupted my development environment. Thus, I dropped them. Anyway, I checked them pragmatically – I let them run and if I couldn’t find any errors, allowed them to stay. Same is true for your PEM Editor. I don’t have the time to double check what’s going on under the hood of a tool, first. If PEM Editor would corrupt one of my VCXs, I would delete PEM Editor – that’s easy testing, isn’t it ? ;-)

At the moment I’m working on VFP’s MY namespace extension (this Sedna project) to get it integrated with my ClearAll Blocker to set up some base for a generic Global Resource Manager. I like the MY-concept and if I can make the MY namespace ALWAYS available even after CLEAR ALL, RELEASE ALL, CLOSE ALL (like a built-in system variable), it would be the perfect place to extend its current functionality to become a ResMGR.

Best, Burkhard

Oct 16, 2009 at 8:45 AM

I for instance, have to resort to "Clear All" in a legacy app when i edit a form and then build the project. It gives me an error stating that a classlib is in use and cannot be compiled (i use the rebuild all checkbox).
"Clear classlib" doesn't work, nor "clear class". I think it is that some of the classes are containers that use classes from other classlibs or i dunno. 

Anyway, will your "ClearAll Blocker" prevent the Clear All command do it's thing in this particular situation ?

As for sharing the "_shell" variable, couldn't be implemented a registering system where every tool has to register some code to be run by the program that will be placed in _shell when Clear All will be called ?! Of course, every tool has to come with this system and be able to install it but if it's found it should use it, not replace it.

 

Oct 16, 2009 at 2:30 PM
edyshor wrote:

I for instance, have to resort to "Clear All" in a legacy app when i edit a form and then build the project. It gives me an error stating that a classlib is in use and cannot be compiled (i use the rebuild all checkbox).
"Clear classlib" doesn't work, nor "clear class". I think it is that some of the classes are containers that use classes from other classlibs or i dunno. 

Anyway, will your "ClearAll Blocker" prevent the Clear All command do it's thing in this particular situation ?

As for sharing the "_shell" variable, couldn't be implemented a registering system where every tool has to register some code to be run by the program that will be placed in _shell when Clear All will be called ?! Of course, every tool has to come with this system and be able to install it but if it's found it should use it, not replace it.

 

My ClearAll Blocker (apt name :-) as I described it above, was a “first try” only. In fact, today I am far beyond: Blocking a CLEAR ALL cannot be the right thing, especially not if one encounters dangling references, as in your case. BTW, I am afraid, CLEAR CLASS/CLASSLIB will not work while there are outstanding references, anyway! As long as there are instances of a class referenced in memory, neither a CLEAR CLASS/CLASSLIB nor the compiler/builder can do their jobs.

IMHO, a CLEAR ALL is nothing more than a handy shortcut for a sequence of commands run by VFP internally. According to the CLEAR ALL help file, one could say that issuing a CLEAR ALL command will run a sequence like that: RELEASE ALL, DEACTIVATE POPUP ALL, CLEAR POPUPS, DEACTIVATE MENU ALL, CLEAR MENUS, RELEASE MENUS, CLEAR WINDOWS, CLOSE TABLES ALL, CLOSE INDEXES, CLOSE FORMAT, and CLEAR DLLS. Note, that I never checked the exact sequence, which would be next to impossible to detect, but the amount of commands that are launched should be that size. One thing to mention: In reality, it makes a difference if one issues a single CLEAR ALL or is typing in all commands above (one after the other). This depends on the side effects of each single command. E.g.: a RELEASE ALL would kill the PEM-Editor completely, whereas as CLEAR ALL allows it to restart (if one has enabled that option, naturally). Another example is CLEAR WINDOWS, which (as a single command) works even more “destructively” as the comparable action that takes place during a CLEAR ALL run. Those side effects are ranging from obvious to subtle and weird! Maybe in your case a RELEASE ALL would do the job?

After all, I’m just busy working on a highly enhanced version of my blocker, called Global Resource Manager (GRM). Have a look here. The idea behind this vehicle is, to combine an absolute bullet-proof resistant VFP-Form (the HOST) with the Sedna MY project. The result is a global MY-reference that is unbreakable like any other VFP system variable. At this stage, the GRM exposes some needful new events everybody can bind to: EvtClearAll, EvtCloseAll and EvtReleaseAll are already up und running. When the GRM detects one of these destructive commands, it will block them and replace them by its own command sequence (which can be adapted) if the feature is wanted and enabled. The MY-project can be expanded very easily – I’ve already added a module called UBForms (UnBreakable Forms). You can use it like so: My.UbForms.Add(_oBrowser) e.g. to make the current Class Browser instance CLEAR ALL resistant. Of course, you can also issue a real CLEAR ALL by a simple click (there is a button with “ClearAll” functionality on the GRM form :-)

BTW, the creators of the PEM editor already solved your suggestion for sharing the _SHELL variable very smartly by creating some kind of semaphore file and a restart command file everyone can use and write to during “Clear All” destruction.

Hope this helps

<!--[if gte mso 9]><xml> <o:DocumentProperties> <o:Version>12.00</o:Version> </o:DocumentProperties> <o:OfficeDocumentSettings> <o:RelyOnVML /> <o:AllowPNG /> </o:OfficeDocumentSettings> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves /> <w:TrackFormatting /> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning /> <w:ValidateAgainstSchemas /> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF /> <w:LidThemeOther>DE</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables /> <w:SnapToGridInCell /> <w:WrapTextWithPunct /> <w:UseAsianBreakRules /> <w:DontGrowAutofit /> <w:SplitPgBreakAndParaMark /> <w:DontVertAlignCellWithSp /> <w:DontBreakConstrainedForcedTables /> <w:DontVertAlignInTxbx /> <w:Word11KerningPairs /> <w:CachedColBalance /> </w:Compatibility> <m:mathPr> <m:mathFont m:val="Cambria Math" /> <m:brkBin m:val="before" /> <m:brkBinSub m:val="--" /> <m:smallFrac m:val="off" /> <m:dispDef /> <m:lMargin m:val="0" /> <m:rMargin m:val="0" /> <m:defJc m:val="centerGroup" /> <m:wrapIndent m:val="1440" /> <m:intLim m:val="subSup" /> <m:naryLim m:val="undOvr" /> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal" /> <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9" /> <w:LsdException Locked="false" Priority="39" Name="toc 1" /> <w:LsdException Locked="false" Priority="39" Name="toc 2" /> <w:LsdException Locked="false" Priority="39" Name="toc 3" /> <w:LsdException Locked="false" Priority="39" Name="toc 4" /> <w:LsdException Locked="false" Priority="39" Name="toc 5" /> <w:LsdException Locked="false" Priority="39" Name="toc 6" /> <w:LsdException Locked="false" Priority="39" Name="toc 7" /> <w:LsdException Locked="false" Priority="39" Name="toc 8" /> <w:LsdException Locked="false" Priority="39" Name="toc 9" /> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption" /> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title" /> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font" /> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle" /> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong" /> <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Emphasis" /> <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text" /> <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 1" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision" /> <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph" /> <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote" /> <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 2" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 4" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 6" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6" /> <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis" /> <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis" /> <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference" /> <w:LsdException Locked="false" Priority="32" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference" /> <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title" /> <w:LsdException Locked="false" Priority="37" Name="Bibliography" /> <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading" /> </w:LatentStyles> </xml><![endif]--><!-- /* Font Definitions */ @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:612.0pt 792.0pt; margin:70.85pt 70.85pt 2.0cm 70.85pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} --><!--[if gte mso 10]> <mce:style><! /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Normale Tabelle"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:"Times New Roman"; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin;} --> <!--[endif]-->

My ClearAll Blocker (apt name :-) as I described it above, was a “first try” only. In fact, today I am far beyond.

Blocking a CLEAR ALL cannot be the right thing, especially not if one encounters dangling references, as in your case. BTW, I am afraid, CLEAR CLASS/CLASSLIB will not work while there are outstanding references, anyway! As long as there are instances of a class referenced in memory, neither a CLEAR CLASS/CLASSLIB nor the compiler/builder can do their jobs.

IMHO, a CLEAR ALL is nothing more than a handy shortcut for a sequence of commands run by VFP internally. According to the CLEAR ALL help file, one could say that issuing a CLEAR ALL command will run a sequence like that: RELEASE ALL, DEACTIVATE POPUP ALL, CLEAR POPUPS, DEACTIVATE MENU ALL, CLEAR MENUS, RELEASE MENUS, CLEAR WINDOWS, CLOSE TABLES ALL, CLOSE INDEXES, CLOSE FORMAT, and CLEAR DLLS. Note, that I never checked the exact sequence, which would be next to impossible to detect, but the amount of commands that are launched should be that size. One thing to mention: In reality, it makes a difference if one issues a single CLEAR ALL or is typing in all commands above (one after the other). This depends on the side effects of each single command. E.g.: a RELEASE ALL would kill the PEM-Editor completely, whereas as CLEAR ALL allows it to restart (if one has enabled that option, naturally). Another example is CLEAR WINDOWS, which (as a single command) works even more “destructively” as the comparable action that takes place during a CLEAR ALL run. Those side effects are ranging from obvious to subtle and hard to detect!

After all, I’m just busy working on a highly enhanced version of my blocker, called Global Resource Manager (GRM). Have a look here. The idea behind this vehicle is, to combine an absolute bullet-proof resistant VFP-Form (the HOST) with the Sedna MY project. The result is a global MY-reference that is unbreakable like any other VFP system variable. The GRM exposes some needful new events everybody can bind to: EvtClearAll, EvtCloseAll and EvtReleaseAll are already up und running. When the GRM detects one of these destructive commands, it will block them and replace them by its own command sequence (which can be adapted) if the feature is wanted and enabled. The MY-project can be expanded very easily – I’ve already added a module called UBForms (UnBreakable Forms). You can use it like so: My.UbForms.Add(_oBrowser) e.g. to make the current Class Browser instance CLEAR ALL resistant. Of course, you can also issue a real CLEAR ALL by a simple click (there is a button with “ClearAll” functionality on the GRM form :-)

BTW, the creators of the PEM editor already solved your suggestion for sharing the _SHELL variable very smartly by creating some kind of semaphore file and a restart command file everyone can use and write to during “Clear All” destruction.