I have an AppHandler class that I want to encapsulate other handler
classes (GuiHandler, WmiHandler, etc.) as public properties of the
object, so they can be used like this:

Set oApp = new AppHandler
oApp.NetworkHandler.PingIp sIp

AppHandler, when created, would dynamically load and create the
encapsulated objects.

The concept works fine when applied to something like the native
FileSystemObject:

Dim oApp: Set oApp = new AppHandler
If ( oApp.FileHandler.FileExists("network_handler.class.vbs") ) Then
MsgBox("It works!")
End If

where FileHandler above is a public variable set in the
Class_Initialize method:

Set FileHandler = CreateObject ("Scripting.FileSystemObject")

But in trying to extend this concept to my own classes, I'm running
into problems. The following works (add_module dynamically loads the
file using ExecuteGlobal):

Dim oApp: Set oApp = new AppHandler
oApp.add_module("network_handler.class.vbs")
Set oApp.NetworkHandler = new NetworkHandler

But if I try to internalize this within a public Load method that
calls this private method:

Private Sub m_load_network_handler
add_module(m_nh_path)
Set NetworkHandler = New NetworkHandler
NetworkHandler.debug = debug
NetworkHandler.print_d("NetworkHandler child object loaded")
End Sub

I get an error: "Class Not Defined: NetworkHandler". I've tried a few
workarounds, but nothing has succeeded yet and they tend to lead me
away from my original concept.

Can someone point out my error to me? Is there a scoping issue with
ExecuteGlobal being used inside a private method?

Thanks,
Tom

Re: Encapsulating Objects in Objects? by mr_unreliable

mr_unreliable
Thu Oct 18 10:02:38 PDT 2007

Klenwell, I am having trouble figuring out what language that is.

The "Set oApp = new AppHandler" looks like j(ava)script, but then
there are no semicolons and/or brackets.

Perhaps it is some other language that I'm not familiar with.
But if it's vbScript, then it must be some newer version of vbs
that isn't available here.

If I understand your original question correctly, then yes, it
can be done (in vbs) and I have done it. But I can't offer any
suggestions because I don't know what _your_ version of vbScript
is capable of.

cheers, jw
____________________________________________________________

You got questions? WE GOT ANSWERS!!! ..(but,
no guarantee the answers will be applicable to the questions)




klenwell wrote:
> I have an AppHandler class that I want to encapsulate other handler
> classes (GuiHandler, WmiHandler, etc.) as public properties of the
> object, so they can be used like this:
>
> Set oApp = new AppHandler
> oApp.NetworkHandler.PingIp sIp
>
> AppHandler, when created, would dynamically load and create the
> encapsulated objects.
>
> The concept works fine when applied to something like the native
> FileSystemObject:
>
> Dim oApp: Set oApp = new AppHandler
> If ( oApp.FileHandler.FileExists("network_handler.class.vbs") ) Then
> MsgBox("It works!")
> End If
>
> where FileHandler above is a public variable set in the
> Class_Initialize method:
>
> Set FileHandler = CreateObject ("Scripting.FileSystemObject")
>
> But in trying to extend this concept to my own classes, I'm running
> into problems. The following works (add_module dynamically loads the
> file using ExecuteGlobal):
>
> Dim oApp: Set oApp = new AppHandler
> oApp.add_module("network_handler.class.vbs")
> Set oApp.NetworkHandler = new NetworkHandler
>
> But if I try to internalize this within a public Load method that
> calls this private method:
>
> Private Sub m_load_network_handler
> add_module(m_nh_path)
> Set NetworkHandler = New NetworkHandler
> NetworkHandler.debug = debug
> NetworkHandler.print_d("NetworkHandler child object loaded")
> End Sub
>
> I get an error: "Class Not Defined: NetworkHandler". I've tried a few
> workarounds, but nothing has succeeded yet and they tend to lead me
> away from my original concept.
>
> Can someone point out my error to me? Is there a scoping issue with
> ExecuteGlobal being used inside a private method?
>
> Thanks,
> Tom
>

Re: Encapsulating Objects in Objects? by klenwell

klenwell
Thu Oct 18 12:57:21 PDT 2007

> If I understand your original question correctly, then yes, it
> can be done (in vbs) and I have done it. But I can't offer any
> suggestions because I don't know what _your_ version of vbScript
> is capable of.

The O'Reilly pocket reference I'm using says "Features Version 5.5" on
the cover. I'm building an .hta script for usage on XP.

I worked around my original problem by moving creation of the
encapsulated object to the main script, like so:

Dim oApp: Set oApp = new AppHandler
oApp.Load ' this imports the file for NetworkHandler among others
Set oApp.NetworkHandler = new NetworkHandler

Wasn't able to create NetworkHandler in the m_load_network_handler
method inside AppHandler called by the Load method above as I
originally wanted.

In any event, I'd be curious to see how you or anyone else is doing
it.

Thanks,
Tom


On Oct 18, 10:02 am, mr_unreliable
<kindlyReplyToNewsgr...@notmail.com> wrote:
> Klenwell, I am having trouble figuring out what language that is.
>
> The "Set oApp = new AppHandler" looks like j(ava)script, but then
> there are no semicolons and/or brackets.
>
> Perhaps it is some other language that I'm not familiar with.
> But if it's vbScript, then it must be some newer version of vbs
> that isn't available here.
>
> If I understand your original question correctly, then yes, it
> can be done (in vbs) and I have done it. But I can't offer any
> suggestions because I don't know what _your_ version of vbScript
> is capable of.
>
> cheers, jw
> ____________________________________________________________
>
> You got questions? WE GOT ANSWERS!!! ..(but,
> no guarantee the answers will be applicable to the questions)
>
> klenwell wrote:
> > I have an AppHandler class that I want to encapsulate other handler
> > classes (GuiHandler, WmiHandler, etc.) as public properties of the
> > object, so they can be used like this:
>
> > Set oApp = new AppHandler
> > oApp.NetworkHandler.PingIp sIp
>
> > AppHandler, when created, would dynamically load and create the
> > encapsulated objects.
>
> > The concept works fine when applied to something like the native
> > FileSystemObject:
>
> > Dim oApp: Set oApp = new AppHandler
> > If ( oApp.FileHandler.FileExists("network_handler.class.vbs") ) Then
> > MsgBox("It works!")
> > End If
>
> > where FileHandler above is a public variable set in the
> > Class_Initialize method:
>
> > Set FileHandler = CreateObject ("Scripting.FileSystemObject")
>
> > But in trying to extend this concept to my own classes, I'm running
> > into problems. The following works (add_module dynamically loads the
> > file using ExecuteGlobal):
>
> > Dim oApp: Set oApp = new AppHandler
> > oApp.add_module("network_handler.class.vbs")
> > Set oApp.NetworkHandler = new NetworkHandler
>
> > But if I try to internalize this within a public Load method that
> > calls this private method:
>
> > Private Sub m_load_network_handler
> > add_module(m_nh_path)
> > Set NetworkHandler = New NetworkHandler
> > NetworkHandler.debug = debug
> > NetworkHandler.print_d("NetworkHandler child object loaded")
> > End Sub
>
> > I get an error: "Class Not Defined: NetworkHandler". I've tried a few
> > workarounds, but nothing has succeeded yet and they tend to lead me
> > away from my original concept.
>
> > Can someone point out my error to me? Is there a scoping issue with
> > ExecuteGlobal being used inside a private method?
>
> > Thanks,
> > Tom



Re: Encapsulating Objects in Objects? by ekkehard

ekkehard
Fri Oct 19 05:20:41 PDT 2007

klenwell schrieb:
> I have an AppHandler class that I want to encapsulate other handler
> classes (GuiHandler, WmiHandler, etc.) as public properties of the
> object, so they can be used like this:
>
> Set oApp = new AppHandler
> oApp.NetworkHandler.PingIp sIp
>
> AppHandler, when created, would dynamically load and create the
> encapsulated objects.
>
> The concept works fine when applied to something like the native
> FileSystemObject:
>
> Dim oApp: Set oApp = new AppHandler
> If ( oApp.FileHandler.FileExists("network_handler.class.vbs") ) Then
> MsgBox("It works!")
> End If
>
> where FileHandler above is a public variable set in the
> Class_Initialize method:
>
> Set FileHandler = CreateObject ("Scripting.FileSystemObject")
>
> But in trying to extend this concept to my own classes, I'm running
> into problems. The following works (add_module dynamically loads the
> file using ExecuteGlobal):
>
> Dim oApp: Set oApp = new AppHandler
> oApp.add_module("network_handler.class.vbs")
> Set oApp.NetworkHandler = new NetworkHandler
>
> But if I try to internalize this within a public Load method that
> calls this private method:
>
> Private Sub m_load_network_handler
> add_module(m_nh_path)
> Set NetworkHandler = New NetworkHandler
> NetworkHandler.debug = debug
> NetworkHandler.print_d("NetworkHandler child object loaded")
> End Sub
>
> I get an error: "Class Not Defined: NetworkHandler". I've tried a few
> workarounds, but nothing has succeeded yet and they tend to lead me
> away from my original concept.
>
> Can someone point out my error to me? Is there a scoping issue with
> ExecuteGlobal being used inside a private method?
>
> Thanks,
> Tom
>
Hi Tom,

I *suspect* your problem is caused by re-using the class name (NetworkHandler)
as member variable name. As evidence:

--- main.vbs ---
Option Explicit

Dim goFS : Set goFS = CreateObject( "Scripting.FileSystemObject" )

ExecuteGlobal goFS.OpenTextFile( ".\lib0.vbs" ).ReadAll

WScript.Quit doMain()

Function doMain()
WScript.Echo "doMain() started"
Dim oApp : Set oApp = New AppHandler
oApp.addNetworkHandler
doMain = 0
WScript.Echo "doMain() done"
End Function

--- lib0.vbs ---
Option Explicit

Class AppHandler

' Dim NetworkHandler ' don't use class name as variable name
Dim m_NetworkHandler

Private Sub Class_Initialize()
WScript.Echo "AppHandler::Class_Initialize()"
End Sub

Private Sub Class_Terminate()
WScript.Echo "AppHandler::Class_Terminate()"
End Sub

Public Sub addNetworkHandler
WScript.Echo "AppHandler::addNetworkHandler"
ExecuteGlobal goFS.OpenTextFile( ".\lib1.vbs" ).ReadAll
' Set NetworkHandler = New NetworkHandler
' error: Laufzeitfehler in Microsoft VBScript: Klasse nicht definiert: 'NetworkHandler'
Set m_NetworkHandler = New NetworkHandler
End Sub

End Class

' --- top level code ---

WScript.Echo "lib0.vbs loaded"

--- lib1.vbs ---
Option Explicit

Class NetworkHandler

Private Sub Class_Initialize()
WScript.Echo "NetworkHandler::Class_Initialize()"
End Sub

Private Sub Class_Terminate()
WScript.Echo "NetworkHandler::Class_Terminate()"
End Sub

End Class

' --- top level code ---

WScript.Echo "lib1.vbs loaded"

Output (m_NetworkHandler):

cscript main.vbs
lib0.vbs loaded
doMain() started
AppHandler::Class_Initialize()
AppHandler::addNetworkHandler
lib1.vbs loaded
NetworkHandler::Class_Initialize()
doMain() done
AppHandler::Class_Terminate()
NetworkHandler::Class_Terminate()

I hope this will help you to avoid the workaround, because I like
your original concept of transparent dynamic loading very much.

Ekkehard





Re: Encapsulating Objects in Objects? by klenwell

klenwell
Fri Oct 19 08:58:43 PDT 2007

On Oct 19, 5:20 am, "ekkehard.horner" <ekkehard.hor...@arcor.de>
wrote:
> klenwell schrieb:
>
> > I have an AppHandler class that I want to encapsulate other handler
> > classes (GuiHandler, WmiHandler, etc.) as public properties of the
> > object, so they can be used like this:
>
> > Set oApp = new AppHandler
> > oApp.NetworkHandler.PingIp sIp
>
> > AppHandler, when created, would dynamically load and create the
> > encapsulated objects.
>
> > The concept works fine when applied to something like the native
> > FileSystemObject:
>
> > Dim oApp: Set oApp = new AppHandler
> > If ( oApp.FileHandler.FileExists("network_handler.class.vbs") ) Then
> > MsgBox("It works!")
> > End If
>
> > where FileHandler above is a public variable set in the
> > Class_Initialize method:
>
> > Set FileHandler = CreateObject ("Scripting.FileSystemObject")
>
> > But in trying to extend this concept to my own classes, I'm running
> > into problems. The following works (add_module dynamically loads the
> > file using ExecuteGlobal):
>
> > Dim oApp: Set oApp = new AppHandler
> > oApp.add_module("network_handler.class.vbs")
> > Set oApp.NetworkHandler = new NetworkHandler
>
> > But if I try to internalize this within a public Load method that
> > calls this private method:
>
> > Private Sub m_load_network_handler
> > add_module(m_nh_path)
> > Set NetworkHandler = New NetworkHandler
> > NetworkHandler.debug = debug
> > NetworkHandler.print_d("NetworkHandler child object loaded")
> > End Sub
>
> > I get an error: "Class Not Defined: NetworkHandler". I've tried a few
> > workarounds, but nothing has succeeded yet and they tend to lead me
> > away from my original concept.
>
> > Can someone point out my error to me? Is there a scoping issue with
> > ExecuteGlobal being used inside a private method?
>
> > Thanks,
> > Tom
>
> Hi Tom,
>
> I *suspect* your problem is caused by re-using the class name (NetworkHandler)
> as member variable name. As evidence:
>
> --- main.vbs ---
> Option Explicit
>
> Dim goFS : Set goFS = CreateObject( "Scripting.FileSystemObject" )
>
> ExecuteGlobal goFS.OpenTextFile( ".\lib0.vbs" ).ReadAll
>
> WScript.Quit doMain()
>
> Function doMain()
> WScript.Echo "doMain() started"
> Dim oApp : Set oApp = New AppHandler
> oApp.addNetworkHandler
> doMain = 0
> WScript.Echo "doMain() done"
> End Function
>
> --- lib0.vbs ---
> Option Explicit
>
> Class AppHandler
>
> ' Dim NetworkHandler ' don't use class name as variable name
> Dim m_NetworkHandler
>
> Private Sub Class_Initialize()
> WScript.Echo "AppHandler::Class_Initialize()"
> End Sub
>
> Private Sub Class_Terminate()
> WScript.Echo "AppHandler::Class_Terminate()"
> End Sub
>
> Public Sub addNetworkHandler
> WScript.Echo "AppHandler::addNetworkHandler"
> ExecuteGlobal goFS.OpenTextFile( ".\lib1.vbs" ).ReadAll
> ' Set NetworkHandler = New NetworkHandler
> ' error: Laufzeitfehler in Microsoft VBScript: Klasse nicht definiert: 'NetworkHandler'
> Set m_NetworkHandler = New NetworkHandler
> End Sub
>
> End Class
>
> ' --- top level code ---
>
> WScript.Echo "lib0.vbs loaded"
>
> --- lib1.vbs ---
> Option Explicit
>
> Class NetworkHandler
>
> Private Sub Class_Initialize()
> WScript.Echo "NetworkHandler::Class_Initialize()"
> End Sub
>
> Private Sub Class_Terminate()
> WScript.Echo "NetworkHandler::Class_Terminate()"
> End Sub
>
> End Class
>
> ' --- top level code ---
>
> WScript.Echo "lib1.vbs loaded"
>
> Output (m_NetworkHandler):
>
> cscript main.vbs
> lib0.vbs loaded
> doMain() started
> AppHandler::Class_Initialize()
> AppHandler::addNetworkHandler
> lib1.vbs loaded
> NetworkHandler::Class_Initialize()
> doMain() done
> AppHandler::Class_Terminate()
> NetworkHandler::Class_Terminate()
>
> I hope this will help you to avoid the workaround, because I like
> your original concept of transparent dynamic loading very much.
>
> Ekkehard

Thanks for the suggestion, Ekkehard, and for the nice code examples.
They help out a lot.

The idea that the class name and var name might be conflicting
occurred to me. I thought I had controlled for it in my
troubleshooting, but I know that I was resisting changing either for
the sake of simplicity. I'll try changing the network handler class
name and see if that works.