Instructions for testing the COM Random Stream Sample

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Instructions for testing the COM Random Stream Sample

Blair McGlashan
This section gives step-by-step instructions for running the COM Random
Stream sample as an in-proc COM component implemented by Dolphin and hosted
by a VB client executable. Dolphin Smalltalk XP Pro is required to deploy
Active-X DLLs - this functionality is not available in Dolphin 4.0 or
earlier, or in Value/Standard editions of Dolphin XP. These steps have been
tested on fresh Dolphin Pro installations in fresh installations of Windows
98 (2e), Windows 2000, and Windows XP.

1) Open a Package Browswer and locate the 'COM Random Stream' package.

2) Deploy using preconfigured options ('Deploy Executable' from the context
menu, then press the 'Deploy' button on the first page of the wizard).

This will create corandom.dll in <my docs>\Dolphin Smalltalk 5.0\Object
Arts\Samples\ActiveX\Random\

3) Open a command prompt in that directory.

4) Run the test VB client, randomvbclient.exe, it should report an error
something like (depending on the host OS):

    ---------------------------
    RandomVBClient
    ---------------------------

    Run-time error '429':

    ActiveX component can't create object

    ---------------------------
    OK
    ---------------------------

Note that you must have the Visual Basic 6.0 runtime installed
(MSVBVM60.DLL) on your machine in order to get this far. Most machines will
have this installed (certainly it is present after a fresh installation of
Windows 2000). If the DLL is not installed you will get an error something
like this one from Windows 98:

    ---------------------------
    Error Starting Program
    ---------------------------

    A required .DLL file, MSVBVM60.DLL, was not found.

    ---------------------------
    OK
    ---------------------------

If you get this error (or similar) then the required runtime can be
downloaded from Microsoft
(http://download.microsoft.com/download/vb60pro/Redist/sp5/WIN98Me/EN-US/vbr
un60sp5.exe)

5) Register the DLL with the command line: regsvr32 corandom.dll

If regsvr32.exe should be on the path, but can be found in the windows
system directory.

6) Run the test VB client again, which should work this time. If it comes up
at all, then the COM component implemented by Dolphin has been successfully
created (which means the Dolphin DLL will be loaded into the VB process).
Bash away at the Next button a few times to get a few lotto ticket numbers.

If you are not running on a Windows 9x derivative, then Dolphin will not be
able to bind the type library into the DLL, and consequently it cannot be
automatically registered at stage (5). If this is the case then at step (6)
you will get the message something like the following one, again from
Windows 98:

    ---------------------------
    RandomVBClient
    ---------------------------

    Run-time error '-2147221163 (16r80040155)':

    Automation error

    ---------------------------
    OK
    ---------------------------

This error decodes to 'Interface not registered', which effectively says
that no marshalling code is available for a requested interface. In order to
provide this it is necessary to manually register the type library, which is
quite easy to do:

1) Open up an ActiveX Component Wizard in Dolphin (on the Additional tools
menu)

2) On the first page of the wizard press the 'Browse...' button.

3) In the subsequent dialog press the 'Open...' button.

4) Use the resulting file open dialog to browse to the COM Random Stream
sample directory, i.e. <my docs>\Dolphin Smalltalk 5.0\Object
Arts\Samples\ActiveX\Random\, and open the 'Random.tlb' file.

5) Cancel out of the wizard

The type library should now be registered, so you can attempt to run
randomvbclient.exe again.


Reply | Threaded
Open this post in threaded view
|

Re: Instructions for testing the COM Random Stream Sample

Keith Alcock-3
Blair,

Thanks for instructions.  I tried this out with Windows ME and got it to work.  The only
discrepency was with this:

>
> 6) Run the test VB client again, which should work this time. If it comes up
> at all, then the COM component implemented by Dolphin has been successfully
> created (which means the Dolphin DLL will be loaded into the VB process).
> Bash away at the Next button a few times to get a few lotto ticket numbers.
>
> If you are not running on a Windows 9x derivative, then Dolphin will not be
> able to bind the type library into the DLL, and consequently it cannot be
> automatically registered at stage (5). If this is the case then at step (6)
> you will get the message something like the following one, again from
> Windows 98:
>
>     ---------------------------
>     RandomVBClient
>     ---------------------------
>
>     Run-time error '-2147221163 (16r80040155)':
>
>     Automation error
>
>     ---------------------------
>     OK
>     ---------------------------
>
> This error decodes to 'Interface not registered', which effectively says
> that no marshalling code is available for a requested interface. In order to
> provide this it is necessary to manually register the type library, which is
> quite easy to do:
>

The error message, despite ME being a derivative of 9x was this:

Run-time error '430'

Class does not support Automation or does not support expected interface.


The problem was removed, however, after the type library was registered following your
instructions.

Thanks.

Keith


Reply | Threaded
Open this post in threaded view
|

Re: Instructions for testing the COM Random Stream Sample

Blair McGlashan
"Keith Alcock" <[hidden email]> wrote in message
news:[hidden email]...
> Blair,
>
> Thanks for instructions.  I tried this out with Windows ME and got it to
work.  The only
> discrepency was with this:
> [description of differing error snipped]

Yes, the errors that are reported seem to vary, and I have seen the 430
error.

> ...
> The problem was removed, however, after the type library was registered
following your
> instructions.
>

Right, I'm pleased that worked. Now you might like to know how to debug it
(i.e. run up a development image instead of the deployed DLL) in and out of
process.

To debug in-process just evaluate:
    COMRandomStream register
and then run RandomVBClient again. The registrations should have been
retargeted to the in-process development image launcher, ipdolphin.dll.

In order to debug out-of-process there are four things to consider:
1) There is a bug in the #register method such that it fails to include the
image in the LocalServer32 command line. This is not a problem for a
deployed .EXE (for which #register works fine), because the image is bound
into the .EXE. Aside: The "Image" key is only usable by the in-process
launcher because an out-of-process server has no way of knowing what objects
it will be expected to serve up, apart from what is specified on its command
line. Without an image being specified on the command line Dolphin.exe will
attempt to load "Dolphin.img" from the current working directory when the
server is started.
2) The InProcServer32 registration will take precedence when creating an
object from VB, (I know of know way to explicitly request that the object be
created out-of-process in VB), therefore we need to remove that
registration.
3) When started in "embedded" mode (e.g. as an out-of-process COM server), a
development image will not open any windows apart from the splash screen.
Therefore it is necessary to set break points in relevant places before
saving down the image.
4) We need to ensure the image will register a class factory when it starts,
i.e. evaluate "COMRandomStream registerClassFactory".

All of these apart from (4) can be ignored if one is debugging in a
pre-started image. It is worth trying this first as there is less to go
wrong (basically one doesn't need the registry entries). So having evaluated
"COMRandomStream registerClassFactory" just try running up RandomVBClient to
see if it works. When it is running you should be able to set a breakpoint
in COMRandomStream>>Next: which will be hit when you press the Next button
in the client app.

For starting the image on-demand we need to deal with the registration
issues. The first two points are addressed by the attached patch. With that
installed you can evaluate:
COMRandomStream

                                unregister;

                                register: (OLEConstants at:
#CLSCTX_LOCAL_SERVER).

This will ensure that _only_ a LocalServer32 registration exists, and you
should now be able to run RandomVBClient and get just the splash screen as
an indication that the server has started. If this happens but VB raises an
error (it shouldn't since you've previously managed to register the type
library successfully), then bear in mind that you may need to kill the
out-of-process dolphin task using the task manager before trying again.

Regards

Blair
-------------------------
"DVE - #963"!

!COMInterfaceImp class methodsFor!

progID
 "Answer the receiver's programmatic ID, typically used from scripting or
macro languagues to
 create instances of the receiver, e.g. 'Dolphin.Object.1'. This is not
mandatory, and if not
 specified for the component then the answer will be nil."

 ^nil!

registerAsInProcServer: aRegKey
 | sesh imageFileName |
 sesh := SessionManager current.
 imageFileName := sesh imageFileName.
 sesh isDLL
  ifTrue: [aRegKey at: 'InProcServer32' put: imageFileName]
  ifFalse:
   ["For an executable image we can register the generic in-proc stub for
   in-process activation (but only if it is available)."

   | inProcStub |
   inProcStub := FileLocator installRelative localFileSpecFor: (self
inprocSurrogate: false).
   (File exists: inProcStub)
    ifTrue:
     [aRegKey at: 'InProcServer32' put: inProcStub.
     "The Dolphin specific 'Image' key is needed so the generic stub can
find the image to load"
     aRegKey at: 'Image' put: imageFileName]]!

registerAsLocalServer: aRegKey
 | commandLine sesh |
 commandLine := String writeStream.
 commandLine nextPutAll: (ExternalLibrary moduleFileName: nil).
 sesh := SessionManager current.
 sesh isRuntime
  ifFalse:
   [commandLine
    space;
    nextPut: $";
    nextPutAll: sesh imageFileName;
    nextPut: $"].
 aRegKey at: 'LocalServer32' put: commandLine contents!

register: anInteger
 "Make the necessary registry entries to expose the receiver as a COM object
which can be used by
 other applications for serving objects with the specified class creation
context flags."

 | desc clsid pid clsidKey |
 clsid := self clsid asString.
 desc := self progDescription.
 pid := self progID.
 "First the ProgID to CLSID mappings (if ProgId available)"
 pid notNil
  ifTrue:
   [| vipid pidKey vipidKey |
   vipid := self versionIndependentProgID.
   pidKey := RegKey classesRoot createKey: pid.
   pidKey value: desc.
   pidKey at: 'CLSID' put: clsid.
   vipidKey := RegKey classesRoot createKey: vipid.
   vipidKey
    value: desc;
    at: 'CLSID' put: clsid;
    at: 'CurVer' put: pid].

 "Then the CLSID to server .EXE/.DLL mappings."
 clsidKey := (RegKey classesRoot at: 'CLSID') createKey: clsid.
 clsidKey value: desc.
 pid notNil ifTrue: [clsidKey at: 'ProgID' put: pid].
 (anInteger allMask: CLSCTX_LOCAL_SERVER) ifTrue: [self
registerAsLocalServer: clsidKey].
 (anInteger allMask: CLSCTX_INPROC_SERVER) ifTrue: [self
registerAsInProcServer: clsidKey]!

register
 "Make the necessary registry entries to expose the receiver as a COM object
which can be used by
 other applications. Registry entries for both in-process and out-of-process
use are created if the
 necessary components are present. This (along with #unregister) provides
the necessary mechanism
 for self-registration."

 | sesh |
 sesh := SessionManager current.
 self register: (sesh isDLL
    ifTrue: [CLSCTX_INPROC_SERVER]
    ifFalse:
     [sesh isRuntime
      ifTrue: [CLSCTX_LOCAL_SERVER]
      ifFalse:
       ["For development, register both generic stubs"

       CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER]])! !
!COMInterfaceImp class categoriesFor: #progID!constants!public! !
!COMInterfaceImp class categoriesFor:
#registerAsInProcServer:!helpers!private! !
!COMInterfaceImp class categoriesFor:
#registerAsLocalServer:!helpers!private! !
!COMInterfaceImp class categoriesFor: #register:!operations!public! !
!COMInterfaceImp class categoriesFor: #register!operations!public! !


Reply | Threaded
Open this post in threaded view
|

Re: Instructions for testing the COM Random Stream Sample

Keith Alcock-3
Blair McGlashan wrote:
>
> Right, I'm pleased that worked. Now you might like to know how to debug it
> (i.e. run up a development image instead of the deployed DLL) in and out of
> process.

Blair,

Indeed, that's the first thing I tried and it seemed to work yesterday.  Of course,
it won't today.  I tried it with my own client.  I distinctly remember that all
windows that had been opened when the image was saved reopened, which is not as 3)
below would have.  Maybe it ran the exe instead of dll despite what my program told
it to do.  I don't trust Windows for anything.  Also, it didn't work if I used
Professional.img even though that is what is listed in the registry.  I had to copy
it over to Dolphin.img.  Maybe I'm forgetting to reboot or to reinstall the
operating system after every change :-)

> 3) When started in "embedded" mode (e.g. as an out-of-process COM server), a
> development image will not open any windows apart from the splash screen.
> Therefore it is necessary to set break points in relevant places before
> saving down the image.
> 4) We need to ensure the image will register a class factory when it starts,
> i.e. evaluate "COMRandomStream registerClassFactory".
>

I think that I have followed your instructions for the RandomVBClient.  The result
is

Run-time error '429': ActiveX component can't create object.

and

gpFault reading 0xA0F8B2F

and

Randomvbclient has caused an error in OLE32.DLL

and in addition,

all the development environment windows open, not just the splash screen.

This is with WindowsME, by the way.

Keith