Announcement

Collapse
No announcement yet.

Question about CreateObject

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question about CreateObject

    I just created my first PB based COM server and tried to use it with vbScript. I assumed that the syntax should be:

    Set Obj = CreateObject("EPSON_822.Projector")

    Since my CLASS=EPSON_822 and my INTERFACE=Projector. However, the object fails to be created.

    But when I use only the Class name without the interface name it works. ie:

    Set Obj = CreateObject("EPSON_822")

    I've never seen this before and I don't understand it. The following are examples of objects that I use frequently and they all require the CLASS.INTERFACE syntax.

    Set GUIDGEN = CreateObject("GUIDGenerator.GUIDGEN")
    Set Connection = CreateObject("ADODB.Connection")
    Set Recordset = CreateObject("ADODB.Recordset")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set objMailSender = CreateObject("Persits.MailSender")

    Can anyone tell me what I'm missing? Obviously there's a large gap in my understanding.

    -Wes
    Last edited by WesWesthaver; 5 Feb 2009, 01:07 PM.

  • #2
    But when I use only the Class name without the interface name it works. ie:
    Can anyone tell me what I'm missing? Obviously there's a large gap in my understanding.
    Let me give you a hint.
    Did you assign a programmatic id to the coclass?
    Dominic Mitchell
    Phoenix Visual Designer
    http://www.phnxthunder.com

    Comment


    • #3
      Originally posted by Dominic Mitchell View Post
      Let me give you a hint.
      Did you assign a programmatic id to the coclass?
      Well, I'm so new to this stuff that I'm not sure what you mean. Here's what my code looks like:

      Code:
      '------------------------------------------------------------------------------
      ' Compiler meta statements
      '------------------------------------------------------------------------------
      '
      #Compile Dll
      #Dim All
      #Com Name "EPSON_822", 1.00
      #Com Guid Guid$("{96743A31-E8AB-48F4-919C-8A0B9BC25D5D}")
      #Com TLib On
       
      '------------------------------------------------------------------------------
      ' Projector class
      '   Provides the basic control interface for a generic data projector
      '------------------------------------------------------------------------------
      '
      Class EPSON_822 Guid$("{B4E61282-8F67-4AE9-B3F1-79771CB93D2B}") As Com
        '----------------------------------------------------------------------------
        ' Instance variables
        '
        Instance strIP        As String
        Instance lngPort      As Long
        '----------------------------------------------------------------------------
        ' Class interface
        '
        Interface Projector Guid$("{698E3BCA-3ADB-4918-A9B3-461044C5754F}")
          '--------------------------------------------------------------------------
          ' Inherit from idispatch base class
          '
          Inherit IDispatch
       
          '--------------------------------------------------------------------------
          ' Properties
          '--------------------------------------------------------------------------
          Property Get IP <30> () As String
            Property = UCode$(strIP)
          End Property
          Property Set IP <30> (ByVal strNewValue As String)
            strIP = ACode$(strNewValue)
          End Property
          '--------------------------------------------------------------------------
          Property Get Port <40> () As Long
            Property = lngPort
          End Property
          Property Set Port <40> (ByVal lngNewValue As Long)
            lngPort = lngNewValue
          End Property
          '--------------------------------------------------------------------------
          Property Get Power <50> () As Byte
            Property = me.GetPower
          End Property
          Property Set Power <50> (ByVal bytNewValue As Byte)
            me.SetPower(bytNewValue)
          End Property
          '--------------------------------------------------------------------------
          Property Get Volume <60> () As Byte
            Property = me.GetVolume
          End Property
          Property Set Volume <60> (ByVal bytNewValue As Byte)
            me.SetVolume(bytNewValue)
          End Property
          '--------------------------------------------------------------------------
          Property Get VideoSource <70> () As Byte
            Property = me.GetVideoSource
          End Property
          Property Set VideoSource <70> (ByVal bytNewValue As Byte)
            me.SetVideoSource(bytNewValue)
          End Property
          '--------------------------------------------------------------------------
          Property Get LampHours <80> () As Integer
            Property = me.GetLampHours
          End Property
       
          '--------------------------------------------------------------------------
          ' Methods
          '--------------------------------------------------------------------------
          '
          Method On <10> ()
            me.SetPower(1)
          End Method
          Method Off <20> ()
            me.SetPower(0)
          End Method
       
        End Interface
       
        '----------------------------------------------------------------------------
        ' Private class methods
        '----------------------------------------------------------------------------
        '
        Class Method Create()
          ' Initialize IP and Port vars.
          '
          strIP = "0.0.0.0"
          lngPort = 3629
        End Method
        Class Method Destroy()
          ' Do nothing.
        End Method
        '----------------------------------------------------------------------------
        Class Method GetPower() As Byte
          Local strResponse As String
          strResponse = me.ProjectorCommand("PWR?" + $Cr, 5)
          Method = Val(me.GetValueFromNVP(strResponse, "PWR"))
        End Method
        Class Method SetPower(bytNewValue As Byte)
          Select Case bytNewValue
            Case 0
              me.ProjectorCommand("PWR OFF" + $Cr, 60)
            Case Else
              me.ProjectorCommand("PWR ON"  + $Cr, 60)
          End Select
        End Method
        '----------------------------------------------------------------------------
        Class Method GetVolume() As Integer
          Local strResponse As String
          strResponse = me.ProjectorCommand("VOL?" + $Cr, 5)
          Method = Val(me.GetValueFromNVP(strResponse, "VOL"))
        End Method
        Class Method SetVolume(bytNewValue As Byte)
          me.ProjectorCommand("VOL" + Str$(bytNewValue) + $Cr, 5)
        End Method
        '----------------------------------------------------------------------------
        Class Method GetVideoSource() As Integer
          Local strResponse As String
          strResponse = me.ProjectorCommand("SOURCE?" + $Cr, 5)
          Method = Val(me.GetValueFromNVP(strResponse, "SOURCE"))
        End Method
        Class Method SetVideoSource(bytNewValue As Byte)
          me.ProjectorCommand("SOURCE" + Str$(bytNewValue) + $Cr, 5)
        End Method
        '----------------------------------------------------------------------------
        Class Method GetLampHours() As Integer
          Local strResponse As String
          strResponse = me.ProjectorCommand("LAMP?" + $Cr, 5)
          Method = Val(me.GetValueFromNVP(strResponse, "LAMP"))
        End Method
       
        '----------------------------------------------------------------------------
        ' TCP/IP communication methods
        '----------------------------------------------------------------------------
        '
        Class Method ProjectorConnect(lngTimeout As Long) As Long
       
          ' Code removed because of NDA
       
        End Method
        '----------------------------------------------------------------------------
        Class Method ProjectorDisconnect(lngFileNum As Long)
          Tcp Close lngFileNum
        End Method
        '----------------------------------------------------------------------------
        Class Method ProjectorCommand(strCommand As String, lngTimeout As Long) As String
          Local lngFileNum As Long
          lngFileNum = me.ProjectorConnect(lngTimeout)
          Me.TX(lngFileNum, strCommand)
          Method = me.RX(lngFileNum,":")
          me.ProjectorDisconnect(lngFileNum)
        End Method
        '----------------------------------------------------------------------------
        Class Method TX(lngFileNum As Long, strCommand As String)
          Tcp Send lngFileNum, strCommand
        End Method
        '----------------------------------------------------------------------------
        Class Method RX(lngFileNum As Long, strEOT As String) As String
          Local strTemp    As String
          Local strBuffer  As String
          strTemp = ""
          strBuffer = ""
          Do
            Tcp Recv lngFileNum, 1024, strBuffer
            strTemp = strTemp + strBuffer
            If IsTrue Err Then
              MsgBox "RX: Error=" + Str$(Err),, "EPSON_822.DLL"
              ErrClear
              Exit Do
            End If
            If strBuffer = "" Then
              MsgBox "RX: buffer empty",, "EPSON_822.DLL"
              Exit Do
            End If
            If strEOT <> "" Then
              If InStr(strTemp, strEOT) Then
                'msgbox "RX: EOT",, "EPSON_822.DLL"
                Exit Do
              End If
            End If
          Loop
          Method = strTemp
        End Method
        '----------------------------------------------------------------------------
        Class Method GetValueFromNVP(strInput As String, strFind As String) As String
          Local intIndex   As Integer
          Local strArray() As String
          Local strName    As String
          Local strValue   As String
          Dim strArray(1 To ParseCount(strInput, $Cr))
          Parse strInput, strArray(), $Cr
       
          ' Check for error in projector response
          '
          For intIndex = 1 To UBound(strArray)
            If Left$(strArray(intIndex), 3) = "ERR" Then
              MsgBox "Projector returned an ERR",, "EPSON_822.DLL"
              Method = ""
              Exit Method
            End If
          Next intIndex
          ' Find the specified name and return its value
          '
          For intIndex = 1 To UBound(strArray)
            If Left$(strArray(intIndex), Len(strFind)) = strFind Then
              If InStr(strArray(intIndex), "=") Then
                strName = Extract$(strArray(intIndex),"=")
                strValue = Remain$(strArray(intIndex),"=")
                Method = strValue
                Exit For
              End If
            End If
          Next intIndex
        End Method
      End Class
      And here's the resulting COM Browser info:

      Code:
      ' Generated by: PowerBASIC COM Browser v.2.00.0058
      ' DateTime    : 2/5/2009 at 2:42 PM
      ' ------------------------------------------------
      ' Library Name: EPSON_822
      ' Library File: F:\Projector Control Project\COM\EPSON_822.DLL
      ' Description : COM Library
      ' GUID : {96743A31-E8AB-48F4-919C-8A0B9BC25D5D}
      ' LCID : 0
      ' Version : 1.0
      ' Class Indentifiers
      $CLSID_EPSON_822_EPSON_822 = GUID$("{B4E61282-8F67-4AE9-B3F1-79771CB93D2B}")
      ' Interface Indentifiers
      $IID_EPSON_822_PROJECTOR = GUID$("{698E3BCA-3ADB-4918-A9B3-461044C5754F}")
      ' Interface Name  : PROJECTOR
      ' Description     : PROJECTOR is a dual interface with IDispatch.
      ' ClassID         : $CLSID_EPSON_822_EPSON_822
      Interface PROJECTOR $IID_EPSON_822_PROJECTOR 
          Inherit IDispatch
          Property Get IP <30> () As String
          Property Set IP <30> (ByVal Rhs As String)
          Property Get PORT <40> () As Long
          Property Set PORT <40> (ByVal Rhs As Long)
          Property Get POWER <50> () As Byte
          Property Set POWER <50> (ByVal Rhs As Byte)
          Property Get VOLUME <60> () As Byte
          Property Set VOLUME <60> (ByVal Rhs As Byte)
          Property Get VIDEOSOURCE <70> () As Byte
          Property Set VIDEOSOURCE <70> (ByVal Rhs As Byte)
          Property Get LAMPHOURS <80> () As Integer
          Method ON <10> ()
          Method OFF <20> ()
      End Interface
      Last edited by WesWesthaver; 5 Feb 2009, 01:53 PM.

      Comment


      • #4
        Set Obj = CreateObject("EPSON_822.Projector")

        I don't see where you are getting the .Projector part from Wes. It looks to me like the ProgID doesn't have that part.

        Also, I don't believe IDispatch based objects can have more than one interface, which is by default the 'default interface'. So doing late binding with just the ProgID will give you the first and only interface in the class.
        Fred
        "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

        Comment


        • #5
          You are probably thinking of a programmatic identifier(ProgID) in terms of the unofficial naming convention

          <program>.<component>.<version>

          PowerBASIC just simply uses the class name as the programmatic id. Not a good idea
          in my opinion.
          You have no control over this and a slew of other things unless you decide to tweak the type libary
          file(*.tlb).

          When you register your server with regsvr32.exe, PowerBASIC creates the following entries in the
          Registry:

          HKEY_CLASSES_ROOT\CLSID\{B4E61282-8F67-4AE9-B3F1-79771CB93D2B}\ProgID\EPSON_822
          HKEY_CLASSES_ROOT\TypeLib\{96743A31-E8AB-48F4-919C-8A0B9BC25D5D}\1.0\...

          And that is why CreateObject("EPSON_822") worked.
          Last edited by Dominic Mitchell; 5 Feb 2009, 03:25 PM.
          Dominic Mitchell
          Phoenix Visual Designer
          http://www.phnxthunder.com

          Comment


          • #6
            Hi Wes,

            I'm afraid Dominic isn't entirely correct on this one. Most languages, including PowerBASIC and VB, use a ProgID to identify a CLASS. A ProgID is a relatively short alphanumeric identifier which specifies a particular CLASS on your computer. In effect, it's a shorter, friendlier version of the Class ID (CLSID) which uniquely identifies the class globally. It's expected that a ProgID might be duplicated on computers other than yours, as the nature of the identifier is much simpler.

            Note that a ProgID does not identify a CLASS/INTERFACE combination, but rather, just a CLASS, including all of its interfaces. When you create an object variable in PowerBASIC, the ProgID specifies the CLASS, and the variable definition specifies the interface you wish to use. You combine the two items when you instantiate an object. Most languages follow conventions of that sort.

            Since the ProgID specifies only the CLASS, we've chosen to use the CLASS name as the ProgID. That makes it short, descriptive, and very easy for you to remember. If you'd like to make it more complex, and therefore more unique, you only need to change the class name to something much longer, more complicated, and therefore less likely to clash. The choice is entirely in your hands to do with as you wish. If you are more comfortable using a class/interface combination, there's nothing to prevent you from just extending/expanding the class name to suit your whim-of-the-day! {smile}

            Best regards,

            Bob Zale
            PowerBASIC Inc.

            Comment


            • #7
              Wow, I guess I have to plead mea-culpa for my ignorance. In trying to understand what I have been seeing all these years I fashioned a bizzare explanation in my own mind that was entirely bogus.

              It never occured to me that the naming convention I've observed all these years like:

              "ADODB.Connection"
              "ADODB.Recordset"
              "Scripting.FileSystemObject"

              was just that... a naming convention! Somehow I assumed that it was some sort of concatenation of the Class name and the Interface name that was created at compile time.

              Now it appears that it's just a naming convention applied to the ProgID.

              Sometimes I think VisualBasic really is damaging to your abilities as a programer. VB let me accomplish my goals but kept me confused about its inner workings. I guess this is what happens when you've worked with VisualBasic for too many years.

              Anyway, if I wanted to adopt this naming convention, I would do something like this?:

              #COM NAME "ProgramName.ObjectName", 1.00

              or in my particular case

              #COM NAME "ProjectorNET.EPSON_822", 1.00

              -Wes
              Last edited by WesWesthaver; 6 Feb 2009, 10:31 PM.

              Comment


              • #8
                PS. I found this in an MSDN article:

                The format of <ProgID> is <Program>.<Component>.<Version>, separated by periods and with no spaces. The ProgID must comply with the following requirements:
                • Have no more than 39 characters.
                • Contain no punctuation (including underscores) except one or more periods.
                • Not start with a digit.
                • Be different from the class name of any OLE 1 application, including the OLE 1 version of the same application, if there is one.
                So it appears that the use of the underscore in my current COM object ProgID ("EPSON_822") is illegal (even though it seems to work just fine.) Hmmm... so much to take in.
                Last edited by WesWesthaver; 6 Feb 2009, 10:36 PM.

                Comment


                • #9
                  Anyway, if I wanted to adopt this naming convention, I would do something like this?:

                  #COM NAME "ProgramName.ObjectName", 1.00

                  or in my particular case

                  #COM NAME "ProjectorNET.EPSON_822", 1.00
                  No, that is not going to give you the programmatic ID. Because PowerBASIC uses the class name for
                  the programmatic ID, it can never produce one that looks like this

                  <Program>.<Component>.<Version>

                  for the simple reason that, for example, EPSON_822.Projector is not a legal name in PB.

                  In my opinion, PowerBASIC needs a metastatement that allows the programmer to define the programmatic ID.
                  Something like #COM PROGID with the option to set both version dependent and version independent forms.

                  At present, to produce that type of programmatic ID, you will need to write your own DllRegisterServer function.

                  PS. I found this in an MSDN article:
                  ...
                  Ignore the part that deals with length and underscores.
                  Last edited by Dominic Mitchell; 7 Feb 2009, 04:45 AM.
                  Dominic Mitchell
                  Phoenix Visual Designer
                  http://www.phnxthunder.com

                  Comment


                  • #10
                    Wes, what Dominic failed to tell you was the difference between the two names. The #COM NAME metastatement specifies the Application ID (AppID) or the Library ID (LibID), which is the (optional) name of the entire component or server. A ProgID is the name of a single CLASS. Of course, there can optionally be many classes contained within a single COM component (server).

                    I see that he also extended permission {smile} to ignore certain COM rules regarding naming conventions. Even so, PowerBASIC recommends that you follow those rules for best results.

                    Best regards,

                    Bob Zale
                    PowerBASIC Inc.

                    Comment


                    • #11
                      Originally posted by Dominic Mitchell View Post
                      Because PowerBASIC uses the class name for the programmatic ID, it can never produce one that looks like this

                      <Program>.<Component>.<Version>

                      for the simple reason that, for example, EPSON_822.Projector is not a legal name in PB.
                      Dominic, If you're right, that seems like a really odd design decision to build the compiler in such a way that it won't allow you to name your COM objects in the format that virtually everyone in the industry uses??? That's kind of disappointing. How often does PB get updated? Maybe this can be addressed in the near future? Along with Enums and property attributes....

                      -Wes

                      Comment


                      • #12
                        Two thoughts:
                        #COMBASE "BaseName"
                        #COMBASE DLL
                        #COMBASE NOTHING

                        Is that three? *smack*
                        LarryC
                        Website
                        Sometimes life's a dream, sometimes it's a scream

                        Comment


                        • #13
                          Sometimes I think VisualBasic really is damaging to your abilities as a programer. VB let me accomplish my goals but kept me confused about its inner workings. I guess this is what happens when you've worked with VisualBasic for too many years.
                          Duh. Ya Think?
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment

                          Working...
                          X