Results 1 to 2 of 2

Thread: There can be only one... [VB6 DCOM Singleton]

  1. #1

    Thread Starter
    PowerPoster Dave Sell's Avatar
    Join Date
    Mar 2004
    Location
    /dev/null
    Posts
    2,961

    There can be only one... [VB6 DCOM Singleton]

    And maybe it's not supposed to be done, but I got Matt Curland's ActiveX EXE Singleton Server working with DCOM.

    Huh?!?!?!

    From "Design Patterns," p.127:
    Ensure a class has one instance, and provide a global point of access to it.
    Matt Curland's book "Advanced Visual BAsic 6" has an obscure little chapter in it where he builds on his VBoost power VB object library, in chpater 10 entitled "VB Objects and the Running Object Table." This is also briefly described in an old article, "Give your Classes GetObject Support":
    http://www.ftponline.com/archives/li...MagIssueId=98#

    It is directly from these resources that I was able to get an ActiveX EXE Server to behave as a Singleton. A client will check to see if an instance of the server is out there, and if not, create one. Once that server is up and running, no more instances of the server are created. Instead, new clients hold a reference to the same Object. - {EDIT} So far I have not gotten this to work with multiple remote clients. Multplie local clients will all talk to the same server correctly.

    There can be only one...
    Somewhere, through all the code and documentation I waded through lo these many moons, I did read a caveat - the Singleton built on VBoost objects is not designed to work with DCOM and sounded guaranteed not to work - although I think that might apply to VB5 projects (this is all VB6).

    Well, being a stubborn fool, I went to work and tried it anyway. Looks like I got it working to a point where I can start to look at making it more robust. But before I do, I wanted to document all that I did so far.

    Code first, pics second...

    The project requires that you have some of Matt Curland's VBoost files in the project. If you own a copy of his book, then you have them:
    [list=1][*]ROTHook.bas[*]VBoost.bas[/list=1]
    The other files I will provide are not CopyRight-ed.
    [list=1][*]StateServer.vbp[*]frmMain.frm[*]modMain.bas[*](ROTHook.bas)[*](VBoost.bas)[*]clsState.cls[*]UseStateServer.vbp[*]frmClient.frm[/list=1]

    frmMain.frm
    VB Code:
    1. Option Explicit
    2. '
    3. Private WithEvents m_State As clsState
    4. '
    5. '
    6.  
    7. Private Sub Form_Load()
    8. On Error Resume Next
    9.     Set m_State = GetObject(, "StateServer.clsState")
    10. On Error GoTo 0
    11.     If m_State Is Nothing Then
    12.         Set m_State = New clsState
    13.     End If
    14.     m_State.Locked = True
    15.     Me.lblState.Caption = m_State.State
    16. End Sub
    17.  
    18. Private Sub Form_Unload(Cancel As Integer)
    19.     m_State.Locked = False
    20.     Set m_State = Nothing
    21. End Sub
    22.  
    23. Private Sub m_State_State(ByVal Current As Variant)
    24.     ' This is an Event
    25.     Me.lblState.Caption = Current
    26. End Sub
    27.  
    28. Private Sub txtState_Change()
    29.     m_State.State = Me.txtState.Text
    30. End Sub

    modMain.bas
    VB Code:
    1. Option Explicit
    2. '
    3. Private m_ServerForm As frmMain
    4. '
    5.  
    6. Public Sub EnsureServerForm()
    7.     If m_ServerForm Is Nothing Then
    8.         Set m_ServerForm = New frmMain
    9.         m_ServerForm.Show
    10.     End If
    11. End Sub
    12.  
    13. Sub Main()
    14.     InitVBoost
    15.     '
    16.     If App.StartMode = vbSModeStandalone Then
    17.         EnsureServerForm
    18.     End If
    19.     '
    20. End Sub

    clsState.cls
    VB Code:
    1. Option Explicit
    2. '
    3. '
    4. Public Event State(ByVal Current As Variant)
    5. Private m_ROTHook As ROTHook
    6. Private m_varState As Variant
    7. '
    8.  
    9.  
    10. Private Sub Class_Initialize()
    11.     InitROTHook m_ROTHook
    12.     m_ROTHook.Hook.ExposeObject Me, "StateServer.clsState"
    13.     EnsureServerForm
    14. End Sub
    15.  
    16. Private Sub Class_Terminate()
    17.     m_ROTHook.Hook.HideObject
    18. End Sub
    19.  
    20. Friend Property Let Locked(ByVal RHS As Boolean)
    21.     m_ROTHook.Hook.Locked = RHS
    22. End Property
    23.  
    24. Public Property Let State(ByVal vNewValue As Variant)
    25.     m_varState = vNewValue
    26.     RaiseEvent State(m_varState)
    27. End Property
    28.  
    29. Public Property Get State() As Variant
    30.     State = m_varState
    31. End Property

    frmClient.frm
    VB Code:
    1. Option Explicit
    2. '
    3. Private WithEvents m_State As clsState
    4. '
    5. '
    6.  
    7. Private Sub Form_Load()
    8.     '
    9.     ' The following 2 statements seem equivalent
    10.     '
    11.     'Set m_State = StateServer.clsState
    12.     Set m_State = GetObject("", "StateServer.clsState")
    13.     '
    14.     Me.lblState.Caption = m_State.State
    15. End Sub
    16.  
    17. Private Sub m_State_State(ByVal Current As Variant)
    18.     ' This is an Event
    19.     Me.lblState.Caption = Current
    20. End Sub
    21.  
    22. Private Sub txtState_Change()
    23.     m_State.State = Me.txtState.Text
    24. End Sub

    Compile the Server as an ActiveX EXE, and the client as a normal EXE project. You have Binary Compatibility turned on, right?

    Pick a WinXP Pro machine on the LAN to act as the server. On this machine, run DCOMCNFG.EXE to configure DCOM settings as follows (You have to execute the server EXE once):
    http://www.vbforums.com/attachment.p...postid=1822172
    http://www.vbforums.com/attachment.p...postid=1822174
    http://www.vbforums.com/attachment.p...postid=1822175
    http://www.vbforums.com/attachment.p...postid=1822176
    http://www.vbforums.com/attachment.p...postid=1822177

    You could just play around with the client and the server at this point from the server machine. On to the Client machine! Again, the ActiveX EXE server must be copied to the local disk of the client and executed once. Beware, never execute the server on the client directly after DCOM setup - some settings will revert! Again, run DCOMCNFG.EXE to set up the Client as follows:
    http://www.vbforums.com/attachment.p...postid=1822155
    http://www.vbforums.com/attachment.p...postid=1822157
    http://www.vbforums.com/attachment.p...postid=1822163
    http://www.vbforums.com/attachment.p...postid=1822164

    My local SW firewalls have to be turned off for this to work, but that could probably be corrected. I recommend you turn yours off just to get all your ducks in a row.

    Well, assuming you did all that, we are actually done! You can run the Client executable from the Client machine and type something in:
    http://www.vbforums.com/attachment.p...postid=1822165

    Go to the server machine, and you will see it has caught all the state changes:
    http://www.vbforums.com/attachment.p...postid=1822169

    Also note, you can type directly into the server window, and the State-Changing Events will show up on the client.

    I will post executables that you can play with.

    There are some bugs yet to be worked out. For example, if I load the Client EXE on the Client, the Server EXE opens up. However, if I leave the server EXE up, then close the ClientEXE , then re-open the Client EXE, it will not be talking to the Server EXE anymore.

    I may require that the Client cannot terminate itself - I might implement a ClientTerminate Event (initiated at the server) for all the Clients to capture.
    Attached Files Attached Files
    Last edited by Dave Sell; Oct 26th, 2004 at 06:21 AM.

  2. #2

    Thread Starter
    PowerPoster Dave Sell's Avatar
    Join Date
    Mar 2004
    Location
    /dev/null
    Posts
    2,961

    Update:

    I have since gotten multple clients on a network to all get an indirect reference to the SIngleton. The Singleton Raises an Event, and all the clients on the network here it simultaneously.
    Nobody knows what software they want until after you've delivered what they originally asked for.

    Don't solve problems which don't exist.

    "If I had eight hours to cut down a tree, I'd spend six hours sharpening my axe." --- Abraham Lincoln (1809-1865)

    2 idiots don't make a genius.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width