Premise Undocumented method for removing persistant timers when an object is deleted

Motorola Premise

etc6849

Senior Member
The issue is best described by 123 in this 2009 thread:
http://cocoontech.co...eleted-objects/

Basically, when you delete an object, any remaining timers will eventually execute. If these timers point to the deleted object, you'll get an error and the vbscript interpreter will halt. Typically, most of us have used something similar to the line below in these situations:
Code:
system.addTimer this.UpdateInterval,"on error resume next:this.Update = true",1,"Weather_" & this.ObjectID

Note that "on error resume next:" is appended to the timer.

However, this is sloppy and can mask errors. Building upon 123's work, I have figured out that the code below when placed in a "ChileDeleted" (aka "ClassChildDeleted") event method will always remove a persistent timer.
Code:
if this.Name = "" then
	system.removeTimer "Weather_" & this.ObjectID
end if

The attached image shows how I used this method in a new Weather module. After the user creates a home object of type "Weather" and clicks update, and update timer will trigger every 1800 seconds. The code shown will remove this update timer whenever the home object is deleted, assuming its children are still present.

Thus, if you want to use this work around on an object with no children, simply create some hidden child object whenever the object is created. To do this: use a class constructor method and add code similar to this to create an object of type "Object." Note that I also prevent the end user from deleting the object and hide the object.

Code:
' Create an object of type "Object"
set oTmp = this.CreateObject("sys://Schema/System/Object","Foo")
' Hide the object (e.g. 0x2 = 2)
' Set NODELETE for user (e.g. 0x20000 = 131072, but system can still delete)
oTmp.SetValue "Flags", 131074
set oTmp = nothing

Note that the flag definitions are found in this thread: http://cocoontech.co...better-drivers/
 

Attachments

  • timer removal.jpg
    timer removal.jpg
    32 KB · Views: 8
An interesting application of the 'Child Deleted' method!

Being the first day of the New Year, I have free time to quibble about "undocumented" and "sloppy". ^_^

Assuming one enters Builder's "Expert Mode", 'Child Deleted' is listed as an available class method along with its siblings:
Contructor
Virtual Method
Method
Function
Property Change

They are all in plain sight but are not described in Premise's documentation (with the possible exception of Property Change). I guess you can call it 'undocumented' but my idea of undocumented is the 'MoveEx' method. It appears nowhere in Builder but is a very useful class method that allows you to move an object from one place to another in Premise space. I first learned of it from one of Damon Deen's modules where it was employed to rearrange a group of objects in alphabetical order. How useful is that!

Arguably, MoveEx is not completely undocumented because it is described in the HSDK's API documentation. MoveEx and many other methods, not seen in Builder, are available when developing native Premise drivers (using C++). I don't know how many are 'secretly available for use' within Builder but I've confirmed that GetObjectByIndex and InsertEx methods are accessible. I'll hazard a guess that all methods of the IPremiseObject class can be used in Builder .. and that's never been revealed in any of the posts I've read in the original Premise support forum.


Sloppy is as sloppy does and "on error resume next" ain't so. :)

"on error resume next" is a legal VBScript statement for handling run-time exceptions and is part of VBScript's error-handling mechanism. It is similar to, although not as comprehensive as, the structured exception-handling mechanisms found in modern programming languages like C#, Java, Python, JavaScript, C++, etc.

In its simplest form, exception-handling (a.k.a. error-handling) looks like this:
Code:
try {
some code that might produce an exception
}
catch {
some code that handles exceptions created in the 'try' section
}
Instead of a 'catch all' (intentional pun) you can create one 'catch' for each kind of exception:
Code:
try {
some code that might produce an exception
}
catch (exception type 1) {
some code that handles exception type 1
}
catch (exception type 2) {
some code that handles exception type 2
}

You can emulate this style of exception-handling in VBScript using its Err object (the forum's code-syntax-highlighting is messed up for VBScript)
Code:
err.clear ' reset the err object for good measure
on error resume next ' if an error is encountered, ignore it and continue running
' some code goes here
' that might raise an error
' that we will handle
' in the code below
if err.number [] 0 then
   ' err.number contains the error code and will be non-zero if an error occurred
   ' err.description contains the error message
   select case err.number
	 case 1: ' handle error type 1
	 case 2: ' handle error type 2
	 case else: ' handle all other error types
   end select
end if

If you're not interested in handling the error, and simply want to ignore it, then "on error resume next" is your friend. Ignoring the complaints of 'parentless timers' sounds cruel but "on error resume next", being the cold-blooded code that it is, does it without qualms. Even VBScript's modern replacement, Powershell, has a means of ignoring run-time errors ($erroractionpreference = "SilentlyContinue").

If you want to stop ignoring errors, include a "on error goto 0" statement and that effectively limits what is ignored and what isn't.
Code:
on error resume next
' any code failures here
' will be ignored
on error goto 0
' code failures here
' are no longer ignored

If your Timer has to execute several lines of code, you're better off creating a class method specifically for your Timer. For example, if you create a method called "OnTimer", containing a jillion lines of code (that may incur an error), you can call it with your timer. Here's a simple 60 second Timer, called MyTimer, that runs OnTimer upon expiration:

system.addTimer 60, "on error resume next: this.OnTimer", 1, "MyTimer"

After 60 seconds expires, MyTimer executes its payload, namely "on error resume next: this.OnTimer", and attempts to run "this.OnTimer". If the "this" object no longer exists, because it was deleted by the end-user, no harm no foul because "on error resume next" suppresses the error. If "this" does exist, then the OnTimer method is executed without having any of its potential errors suppressed because it is no longer within the scope of the "on error resume next" statement.


FWIW, Eric Lippert does a great job of explaining the intricacies of programming languages and blogged about VBScript many years ago. From his blogs, here is a list of the Err object's error numbers and their associated descriptions.
 
Thanks for this very indepth tutorial on error handling in vbscript!

Sorry for the novice questions below, but I could be missing something and want to make sure I fully understand error handling since you were kind enough to give this nice overview.

1. I think what makes using on error resume next with timers ok, without the use of on error goto 0, is that a timer's code must be interpreted as a seperate method by SYS' vbscript interpreter, so the "on error resume next" only applies to that timer (e.g. associated method) only? This seems to jive with how timers are shown in builder: when you click on a timer, you see a property change method as a child.

2. Interestingly, in your error catching example "on error goto 0" is missing. I'm assuming it should be placed just after my whatever code that might raise an error like normal...?

Many thanks 123!
 
If I've understood your questions correctly, they both deal with the subject of scope. The scope of the 'on error resume next' statement continues until it encounters 'on error goto 0' or the end of the subroutine. Eric Lippert explains scope in this blog post and it's a worthwhile read.

In my example, 'on error resume next' precedes a group of statements that might fail. Immediately after the error-prone statement, I test err.number to check if the statement failed.

Here's a snippet of code, from my TextToSpeech module, which attempts to open a file. If it failed to open the file, it cleans up, logs the event, and exits the subroutine. Note the placement of the 'on error' statements. (This forum assumes all code examples are Javascript so this VBScript example's colour-highlighting is all messed up).

Code:
....
  on error resume next
  err.clear
  oOutFile.Open sTarget, 3 ' Open for reading and writing
  if err.number = 0 then
   set oSpeech.AudioOutputStream = oOutFile
  else ' Encountered an error while opening the file
   set oOutFile = nothing
   this.LogEvent "Unable to open the output file: " & sTarget, 50, this
   exit sub
  end if
  on error goto 0
else
....

BTW, if you like software 'Easter Eggs' then you've love this one. Typically, a class offers Constructor and Destructor methods; one runs when an object is created whereas the other runs when the object is destroyed. A Destructor method would be the ideal candidate for housekeeping chores like removing leftover timers.

The PremiseObject class offers a Constructor method and is seen in Builder as 'Class Constructor'. However, there is no 'Class Destructor' method. Or is there?

Open \Premise\sys\schema\_schema.xml in a text-editor and scroll down to about 75% of the file. You'll find this gem commented-out:
Code:
<!--
<Class Name="ClassDestructor" DisplayName="Destructor" Icon="scriptevent.ico" DefaultView="sys://Schema/Scripting/Scriptlet/Editor" ID="{B590DE05-5B6D-4c0c-9826-A5D226A3BD38}">
  <SuperClass Name="ClassScript" LinkObject="sys://Schema/Scripting/ClassScript" ID="{D3BD0E99-6F75-4c87-9575-F68041415F38}"/>
</Class>
-->

I uncommented it, restarted Premise SYS Server, opened Builder and, ta-dah!, there's 'Class Destructor' in Builder. Unfortunately, it's all a big tease because any code entered in the Destructor is never executed. In fact, you can type anything you want in the Destructor because Builder doesn't even perform syntax-checking. Maybe Destructors were a planned feature for a future version of Premise.
 
Back
Top