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. |
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 |
"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! ! |
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 |
Free forum by Nabble | Edit this page |