Dolphin Smalltalkers,
Can I prevail upon someone to write one page of documentation on using Dolphin as a COM server? So far I have reread some of Inside COM, checked the Wiki, looked at Bill's newCOMer, read all the class and method comments that seem pertinent, and gone through DSDN. Still, I have to resort to trial and error programming (i.e., hacking) with the emphasis on error. It is very frustrating when compared to normal Smalltalk development. If anyone can provide some material, I'll add it to the Wiki or edit it for the archives. What I would like to see is an extremely simple example. It should not require marshalling or MIDL. I think that some steps are required that are not normally included in code such as one or more calls to the methods register and compileFunctions. These should be documented as well. So far I have classes IMyTest and COMMyTest inheriting from IUnknown and COMInterfaceImp and I'd like to call the method Test. IMyTest class>>defineFunctions "Evaluate IMyTest compileFunctions to transform this information into an instance method." self defineFunction: #Test: argumentTypes: 'DWORD'. IMyTest class>>clsid "This was demanded when I tried to evaluate IMyTest new Test: 6. The implementation may be incorrect." "^self guid." "pick one" ^COMMyTest clsid. "pick one" IMyTest>>Test: aDWORD "Callout for the IMyTest::Test() interface function. N.B. This method has been automatically generated from the vtable defined in IReadSmart>>defineFunctions. DO NOT MODIFY!" <virtual stdcall: HRESULT 4 DWORD> ^self invalidCall COMMyTest class>>clsid ^self guid. COMMyTest class>>progID ^'Dolphin.MyTest.1'. COMMyTest>>supportedInterfaces ^(Array with: IMyTest). COMMyTest>>Test: aDWORD self halt. ^S_OK. Both classes have been registered and unregistered several times, but the information in the registry for clsid and progid look OK. I can't be sure about iid. It looks like IMyTest>>Test: can be used to call the test function from within Dolphin. If I evaluate IMyTest new Test: 6, then another copy of Dolphin starts up. Unfortunately, I get a walkback which implies an error CO_E_SERVER_EXEC_FAILURE, which is what is returned from the C++ program. Here's what that looks like: #include <stdio.h> #include <objbase.h> #include <assert.h> interface IMyTest:IUnknown { virtual HRESULT __stdcall Test(int anInteger)=0; }; extern "C" { IID IID_IMyTest; } int main() { CLSID clsid; HRESULT hresult; wchar_t *string; IMyTest *pIMyTest=NULL; hresult=CoInitialize(NULL); assert(hresult==NOERROR); // Test for version 1. hresult=CLSIDFromProgID(L"Dolphin.MyTest.1",&clsid); assert(hresult==NOERROR); // This should be the clsid of COMMyTest hresult=StringFromCLSID(clsid,&string); assert(hresult==NOERROR); CoTaskMemFree(string); // This should be the clsid of IMyTest hresult=IIDFromString(L"{96FF772E-7345-46BC-B659-4E4DE96B5FCA}",&IID_IMyTest); assert(hresult==NOERROR); hresult=CoCreateInstance(clsid,NULL,CLSCTX_SERVER, IID_IMyTest,(void **) &pIMyTest); assert(hresult==NOERROR); if (SUCCEEDED(hresult)) { pIMyTest->Test(10); pIMyTest->Release(); } CoUninitialize(); return 0; } This chokes up at CoCreateInstance with CO_E_SERVER_EXEC_FAILURE. It does try to start Dolphin, which is encouraging. It has taken hours and hours two write these 20 lines of code and they don't even work. I think that some documentation is called for here. Will anyone make a donation? Keith Alcock |
"Keith Alcock" <[hidden email]> wrote in message
news:[hidden email]... > Dolphin Smalltalkers, > > Can I prevail upon someone to write one page of documentation on using Dolphin as a COM server? So far > I have reread some of Inside COM, checked the Wiki, looked at Bill's newCOMer, read all the class and > method comments that seem pertinent, and gone through DSDN. Still, I have to resort to trial and error > programming (i.e., hacking) with the emphasis on error. It is very frustrating when compared to normal > Smalltalk development. If anyone can provide some material, I'll add it to the Wiki or edit it for the > archives. > Presumably you have read: http://www.object-arts.com/wiki/html/Dolphin/ImplementingActiveXComponents.h tm It is a little dated, and spends a lot of time covering how to create the type library/marshalling DLL in VC++, which is really not necessary, but it does cover the topic. > What I would like to see is an extremely simple example. It should not require marshalling or MIDL. ... Unfortunately you will not get anywhere without some kind of marshalling capability if you want to invoke Dolphin COM server components from another process. It will just fail in rather opaque ways (rather similar to what you are seeing in fact) as the COM server will be started, but will not be able to return an interface pointer to the client. The easiest way to get marshalling support is to stick to automation compatible data types, and build a type library. Building a type library requires MIDL - there are other ways, but there is no getting away from having to supply full static type declarations for the interface to quite excruciating levels of detail, and such information is not explicitly specified in a traditional Smalltalk program, even a traditional C++ program for that matter. Personally I would recommend starting with the a rought cut of the IDL and refactoring the interfaces as you go along, each time rebuilding the type library with a simple MIDL command line: MIDL /Oicf myidl.idl The type library can then be run through Dolphin's Active-X component wizard to automatically generate the required interface classes. These can be regenerated when you change it, although you may then have some manual work to do to modify code in the implementation class if you have modified the definition of existing methods. Auto-generating the interface class at least avoids having to write the class side function table yourself, balancing out some of the work required to write the IDL in the first place. Without some kind of marshalling support you will only be able to test using Dolphin as both client and server within the same image. This is still worth doing, as the calls will be going out as proper virtual function calls, and being implemented as such. As far as the Dolphin client and server are concerned they will not be aware of the identity of the caller and callee. Roughly scanning the wiki pages linked from the above I can see no mention of the need to register (in Dolphin) a class factory for COMInterfaceImp subclass. This need only be done once. This step associates a CLSID with an implementation class, and causes Dolphin to tell COM about the availability of the COM object every time it start. Failure to register the class factory could also explain the problem you are seeing since for an out-of-process server the COM subsystem has to start up the process and then wait for it to register a class factory for the component. Dolphin will only do this if it knows about the COM class, which requires an explicit step, i.e. COMMyTest registerClassFactory Once done this registration lasts until explicitly revoked (assuming you save the image). Note that a running development image will have registered (with COM) class factories for all the server components it knows about. This means that a running development image will service any requests for those components from other processes, which is the next stage of testing after trying with both client and server in Dolphin. The entirety of Dolphin's COM framework, with the exception of a generic virtual table, is implemented in the image, and can therefore be browsed and debugged through. You can set a breakpoint in Dolphin's class factory code, e.g. in COMClassFactory>>CreateInstance:riid:ppvObject:, and debug through the creation of your object. If you find that this all completes successfully, and a valid interface pointer is being returned with an S_OK result, and it still doesn't work for external clients then this is almost certainly because marshalling code is not available. Regards Blair |
Blair,
Thanks for the great deal of effort you put into responding to my email and probably writing some of the WIKI pages. I'm afraid it was to little avail. I had seen the pages on ImplementingActiveXComponents previously and probably dismissed them as too complicated. I looked again today and spent several hours following the directions only to get hresults of large negative numbers. Even if it had worked, the process described is much too complicated and error-prone for me to use it for real projects that other people will eventually have to maintain. There is just zero chance that they could understand, reproduce, debug, or modify it, etc. It still seems to me that documentation is terribly incomplete and outdated. I got errors running registerClassFactory and using the component wizard. The makefiles don't make everything by default and there is no example client that can be used in testing. All sorts of random IDs are running around and there is no good way to make sure that they match up. Knowing that COM is used a great deal by MS, it's a wonder that the computer doesn't crash even more often. Maybe someone can start a night school class on this or do something like Louis Sumberg did with the Personal Money example. Keith Alcock Blair McGlashan wrote: > > "Keith Alcock" <[hidden email]> wrote in message > news:[hidden email].. > > Dolphin Smalltalkers, > > > > Can I prevail upon someone to write one page of documentation on using > Dolphin as a COM server? So far > > I have reread some of Inside COM, checked the Wiki, looked at Bill's > newCOMer, read all the class and > > method comments that seem pertinent, and gone through DSDN. Still, I have > to resort to trial and error > > programming (i.e., hacking) with the emphasis on error. It is very > frustrating when compared to normal > > Smalltalk development. If anyone can provide some material, I'll add it > to the Wiki or edit it for the > > archives. > > > > Presumably you have read: > http://www.object-arts.com/wiki/html/Dolphin/ImplementingActiveXComponents.h > tm > > It is a little dated, and spends a lot of time covering how to create the > type library/marshalling DLL in VC++, which is really not necessary, but it > does cover the topic. > > > What I would like to see is an extremely simple example. It should not > require marshalling or MIDL. ... > > Unfortunately you will not get anywhere without some kind of marshalling > capability if you want to invoke Dolphin COM server components from another > process. It will just fail in rather opaque ways (rather similar to what you > are seeing in fact) as the COM server will be started, but will not be able > to return an interface pointer to the client. > > The easiest way to get marshalling support is to stick to automation > compatible data types, and build a type library. Building a type library > requires MIDL - there are other ways, but there is no getting away from > having to supply full static type declarations for the interface to quite > excruciating levels of detail, and such information is not explicitly > specified in a traditional Smalltalk program, even a traditional C++ program > for that matter. Personally I would recommend starting with the a rought cut > of the IDL and refactoring the interfaces as you go along, each time > rebuilding the type library with a simple MIDL command line: > MIDL /Oicf myidl.idl > The type library can then be run through Dolphin's Active-X component wizard > to automatically generate the required interface classes. These can be > regenerated when you change it, although you may then have some manual work > to do to modify code in the implementation class if you have modified the > definition of existing methods. Auto-generating the interface class at least > avoids having to write the class side function table yourself, balancing out > some of the work required to write the IDL in the first place. > > Without some kind of marshalling support you will only be able to test using > Dolphin as both client and server within the same image. This is still worth > doing, as the calls will be going out as proper virtual function calls, and > being implemented as such. As far as the Dolphin client and server are > concerned they will not be aware of the identity of the caller and callee. > > Roughly scanning the wiki pages linked from the above I can see no mention > of the need to register (in Dolphin) a class factory for COMInterfaceImp > subclass. This need only be done once. This step associates a CLSID with an > implementation class, and causes Dolphin to tell COM about the availability > of the COM object every time it start. Failure to register the class factory > could also explain the problem you are seeing since for an out-of-process > server the COM subsystem has to start up the process and then wait for it to > register a class factory for the component. Dolphin will only do this if it > knows about the COM class, which requires an explicit step, i.e. > > COMMyTest registerClassFactory > > Once done this registration lasts until explicitly revoked (assuming you > save the image). Note that a running development image will have registered > (with COM) class factories for all the server components it knows about. > This means that a running development image will service any requests for > those components from other processes, which is the next stage of testing > after trying with both client and server in Dolphin. The entirety of > Dolphin's COM framework, with the exception of a generic virtual table, is > implemented in the image, and can therefore be browsed and debugged through. > You can set a breakpoint in Dolphin's class factory code, e.g. in > COMClassFactory>>CreateInstance:riid:ppvObject:, and debug through the > creation of your object. If you find that this all completes successfully, > and a valid interface pointer is being returned with an S_OK result, and it > still doesn't work for external clients then this is almost certainly > because marshalling code is not available. > > Regards > > Blair |
In reply to this post by Keith Alcock-3
Keith,
> It has taken hours and hours two write these 20 lines of code and they don't even work. I think that > some documentation is called for here. Will anyone make a donation? I wish I could donate but all I can do is empathize. I've been working on this namespace enumeration for 2 weeks now, and I think that's easy compared to what you're looking at. -- Louis |
In reply to this post by Keith Alcock-3
Keith
What version of Dolphin are you using? Regards Blair |
In reply to this post by Keith Alcock-3
Keith,
Have a look at the newly created http://www.object-arts.com/wiki/html/Dolphin/BuildingCOMponents.htm It's an HTML-formatted copy of one of Blair's recent posts, and well worth reading. > Thanks for the great deal of effort you put into responding to my email and > probably writing some of the WIKI pages. I'm afraid it was to little avail. > > I had seen the pages on ImplementingActiveXComponents previously and probably > dismissed them as too complicated. I looked again today and spent several hours > following the directions only to get hresults of large negative numbers. Even if > it had worked, the process described is much too complicated and error-prone for me > to use it for real projects that other people will eventually have to maintain. > There is just zero chance that they could understand, reproduce, debug, or modify > it, etc. With respect, I think you might be buying into the FUD that often gets spread about Smalltalk. "They'll never be able to understand..." is one of the common arguments against using a wonderfully integrated, reflective and dynamic environment with a simple and consistent syntax. Show me a motivated and intelligent person, and I'll show you another Smalltalker, and a LOT faster than you might think. I caution you against letting the anti-Smalltalk world talk you into underestimating your colleagues' ability to learn new things. > It still seems to me that documentation is terribly incomplete and outdated. I got > errors running registerClassFactory and using the component wizard. The makefiles > don't make everything by default and there is no example client that can be used in > testing. All sorts of random IDs are running around and there is no good way to > make sure that they match up. Microsoft's stuff isn't quite *that* bad :) Sorry, couldn't resist. COM is naturally going to be more difficult to use and debug than straight Smalltalk code. A big part of Smalltalk's appeal is the absence of static typing issues. COM by its nature is _very_ statically typed - it has to be to be able to marshal data across process boundaries. COM keeps information about interfaces and components in the system registry, so there are many ways for things to break due to incorrect entries. Finally, COM marshaling rules allow great flexibility, with a consequence of complicating debugging when things aren't correct. > Knowing that COM is used a great deal by MS, it's a wonder that the computer > doesn't crash even more often. COM is actually quite clean; it's just a lot more trouble to use because it's job is to bridge gaps. It does a good job of bridging gaps though, and the real problem is the gaps themselves. You're not building/debugging one system, but at least two, as well as the glue (marshaling) between them. My intent is not to sound unsympathetic - COM is daunting at first, and I avoid it even now just because it makes things harder, and unless there is a dedicated group of programmers filling in the other side of the gaps, I'd just as soon not have the gaps. Dolphin's COM mapping is as good as it gets. The hard part is writing good IDL. I encourage you to dive in and start swimming; it gets easier faster than you might think. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Blair McGlashan
Blair,
It was supposed to have been 4.01.03, but it looks like I neglected some patches last time I rebuilt the image, so it was only 4.01.01. I'm looking forward to D5 so this can be done in a dll instead of out-of-proc. If I can get it to work I plan to make a wizard in Smalltalk that will produce any IDL code necessary (for very simple cases, at least) and the C++ code to call the server (and any required makefiles, etc). These seems better than relying on the VC++ wizards. This might also include code to verify that the registry entries are as set properly and that the right ones are pointing to Dolphin, etc. Keith Blair McGlashan wrote: > > Keith > > What version of Dolphin are you using? > > Regards > > Blair |
In reply to this post by Bill Schwab-2
Bill,
Thanks for the URL. I'll look right away. Don't worry too much about the other issue you address. The other programmers can probably still figure it out, but my concern was not the Smalltalk code, but rather the machine generated C++ files that are produced by the one-way wizard processes used in a particular example. The code is not readable, contains lots of implicit dependencies, redefines so many things that the debugger is nearly useless, etc., etc. The Smalltalk code is much preferable. Keith Bill Schwab wrote: > > Keith, > > Have a look at the newly created > > http://www.object-arts.com/wiki/html/Dolphin/BuildingCOMponents.htm > > It's an HTML-formatted copy of one of Blair's recent posts, and well worth > reading. > > > Thanks for the great deal of effort you put into responding to my email > and > > probably writing some of the WIKI pages. I'm afraid it was to little > avail. > > > > I had seen the pages on ImplementingActiveXComponents previously and > probably > > dismissed them as too complicated. I looked again today and spent several > hours > > following the directions only to get hresults of large negative numbers. > Even if > > it had worked, the process described is much too complicated and > error-prone for me > > to use it for real projects that other people will eventually have to > maintain. > > There is just zero chance that they could understand, reproduce, debug, or > modify > > it, etc. > > With respect, I think you might be buying into the FUD that often gets > spread about Smalltalk. "They'll never be able to understand..." is one of > the common arguments against using a wonderfully integrated, reflective and > dynamic environment with a simple and consistent syntax. Show me a > motivated and intelligent person, and I'll show you another Smalltalker, and > a LOT faster than you might think. I caution you against letting the > anti-Smalltalk world talk you into underestimating your colleagues' ability > to learn new things. |
In reply to this post by Bill Schwab-2
Bill, Blair,
I tried this excellent step-by-step set of instructions and things were going so well that I was worried about having to explain why my previous attempts were not successful until around about step 9. It probably is the case that my test client is not working correctly, but it is copied from the Rogerson book nearly verbatim. I tried to use the component from VB as well, but could not find it listed anywhere, and I'm not a VB expert, so I gave up on that quickly. The C++ test client gives E_NOINTERFACE. Everyone is probably busy with D5, so this will probably be ignored, but here are some details about the test: 1. This is the exact IDL code from the file called smalltalkmath.idl: [ // IID of interface; MIDL will create a factory for the // proxy stub itself using the same CLSID; they have // different uses so they never collide: uuid(92D770D0-67A2-4de3-B0BB-5027C7CE928A), object, helpstring("Integer Exponent Interface") ] interface IIntegerExponent:IUnknown { import "unknwn.idl"; HRESULT Square( [in] int iInput, [out] int *piOutput ); HRESULT Cube( [in] int iInput, [out] int *piOutput ); HRESULT NoOp( [in] int iInput ); } [ // IID for type library uuid(B66A1A5B-107F-48e7-AB3A-08F1AF479817), version(1.0), helpstring("Smalltalk Math 1.0") ] library SmalltalkMath { importlib("stdole32.tlb"); [ // CLSID of IntegerUnit uuid(E0F76C6B-F2F3-412a-9ABF-0C1C3B73CCA3), helpstring("Component IntegerUnit") ] coclass IntegerUnit { [default] interface IIntegerExponent; }; } It was copied and pasted from various examples. 2. It compiled right away and produced the files dlldata.c, smalltalkmath.h, smalltalkmath_i.c, smalltalkmath_p.c, and smalltalkmath.tlb. 3-8. No problems. 9. I compiled the files smalltalkmath.h and smalltalkmath_i.c that were produced by MIDL with the file smalltalkmath.cpp, which is the test client. That code is #include <stdio.h> #include <objbase.h> #include <assert.h> #include "smalltalkmath.h" int main() { HRESULT hresult; IIntegerExponent *pIIntegerExponent=NULL; hresult=CoInitialize(NULL); assert(hresult==NOERROR); hresult=CoCreateInstance(CLSID_IntegerUnit,NULL,CLSCTX_SERVER, IID_IIntegerExponent,(void **) &pIIntegerExponent); assert(hresult==NOERROR); if (SUCCEEDED(hresult)) { int result; // pIIntegerExponent->Square(4,&result); // pIIntegerExponent->Cube(5,&result); pIIntegerExponent->NoOp(10); pIIntegerExponent->Release(); } CoUninitialize(); return 0; } This asserts after CoCreateInstance. I am no doubt doing something stupid somewhere. This is definitely a case when a statically typed, compiled language does not guarantee that everything will fit together right. Keith Alcock Bill Schwab wrote: > > Keith, > > Have a look at the newly created > > http://www.object-arts.com/wiki/html/Dolphin/BuildingCOMponents.htm > > It's an HTML-formatted copy of one of Blair's recent posts, and well worth > reading. > |
In reply to this post by Bill Schwab-2
> Dolphin's COM mapping is as good as it gets. The hard part is writing good
> IDL. I encourage you to dive in and start swimming; it gets easier faster > than you might think. > Are there any good references for IDL in particular that you would recommend? |
Howard,
> > Dolphin's COM mapping is as good as it gets. The hard part is writing good > > IDL. I encourage you to dive in and start swimming; it gets easier faster > > than you might think. > > > > Are there any good references for IDL in particular that you would > recommend? You mean other than getting Blair to tell you how to fix it :) Rogererson's Inside COM is a must, and there's an MSJ article www.microsoft.com/msj/0898/idl/idl.htm that's well worth reading. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Howard Ding-2
"Howard Ding" <[hidden email]> wrote in message
news:[hidden email]... > > Dolphin's COM mapping is as good as it gets. The hard part is writing good > > IDL. I encourage you to dive in and start swimming; it gets easier faster > > than you might think. > > > > Are there any good references for IDL in particular that you would > recommend? > There is a book virtually dedicated to it entitled "COM IDL & Interface Design", Dr Al Major, Wrox Press. It is the only text I have seen which satisfactorily explains some of the more complex uses. However it probably goes into more depth than most people will ever need. Regards Blair |
In reply to this post by Keith Alcock-3
Keith Alcock wrote:
> > Dolphin Smalltalkers, > > Can I prevail upon someone to write one page of documentation on using Dolphin as a COM server? So far > I have reread some of Inside COM, checked the Wiki, looked at Bill's newCOMer, read all the class and > method comments that seem pertinent, and gone through DSDN. Still, I have to resort to trial and error > programming (i.e., hacking) with the emphasis on error. It is very frustrating when compared to normal > Smalltalk development. If anyone can provide some material, I'll add it to the Wiki or edit it for the > archives. > etc. Well, I had hoped to follow up this post with an announcement of complete success, but it's not quite there yet. After spending a week meticulously reading the Rogerson book and implementing both client and server in C++, I went back to Smalltalk with the proven IDL code and working client program and proxy DLL and...wouldn't you know, it finally worked! I still haven't figured out where it went wrong before, but it might have to do with the remaining problem: the only way that it works is if I start up Dolphin manually. If Dolphin isn't running I get a CO_E_SERVER_EXEC_FAILURE error in the out-of-proc case and REGDB_E_CLASSNOTREG error in the in-proc case. I still haven't figured out how Windows knows when to use the proxy or how to find it and maybe that is related. Does this error pattern ring a bell for anyone? The pertinent registry entries seem to be HKEY_CLASSES_ROOT CLSID {GUID} - value LocalServer32 - Path\IPDolphin.dll InProcServer32 - Path\Dolphin.exe Image - Path\Professional.img It is interesting that Dolphin must use the image key to figure out which image to load. Nevertheless, it was much easier to implement the server in Smalltalk. Now if only I could call it properly. Bill, don't needle me about asking ;-) Keith Alcock |
Keith,
> it might have to do with the remaining problem: the only way that it works is if I start up Dolphin > manually. If Dolphin isn't running I get a CO_E_SERVER_EXEC_FAILURE error in the out-of-proc case and > REGDB_E_CLASSNOTREG error in the in-proc case. I still haven't figured out how Windows knows when to use > the proxy or how to find it and maybe that is related. Does this error pattern ring a bell for anyone? The fact that it works when Dolphin is running has me wondering whether your server is registered correctly. If you registered the class factory and didn't subsequently unregister it, Dolphin will re-register it on startup. Windows would then find it and not bother looking in the registry, at least for the out of proc server. I've done only limited experimenting with DLL deployment and was never concerned with deploying an EXE with the same interfaces. However, it seems reasonable to be concerned about getting confused or conflicting data in the registry. It might help to unregister the DLL or EXE before registering the other??? I use a "bang on the box" approach to COM debugging. It usually goes something like the following (early out on success): (1) check registration of marshaling DLL or type library (2) look for zombie class factories and ensure that a valid one is registered (3) check registration of server (4) Read Rogerson (5) Ask Blair for help :) The zombie class factory thing might be unique to the way I work; I explicitly register/unregister rather than leaving it to the base system, and one common failure mode involves a couple of confused class factories vs. one working class factory. One of my gizmos is particularly prone to this problem. I have one auto-activated EXE server; the others register class factories when they run. The auto-activated server just recently started taking advantage of Automation types and a type library vs. a custom marshaling DLL, and uses COMInterfaceImp>>register vs. a .REG file to create registry entries - it wasn't broke, so I didn't try to fix it. So far, that all seems to be working, but I'm installing and testing. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill,
Thanks for the reply. If the OA support department doesn't give you a medal soon, then I will. I went through your list and covered 1-4 as good as I can with limited experience, but with no luck. In an attempt to debug this, I've set a breakpoint in COMClassFactory class>>registerAll. When I start up Dolphin manually, this method runs and I get a hard coded breakpoint dialog. My factory is present and everything works well. The client can use the functions provided. However, when Dolphin starts up as a server because my client makes a request instead of me starting it manually, I get no dialog and the request fails. I don't know whether Dolphin starts up differently in the two modes or whether a self halt works when Dolphin functions as a server, but it seems odd that the breakpoint is not catching. Blair is probably busy right now working on that education center documentation :-). I hope that it includes a description of this random example that is under My Documents\Dolphin Smalltalk 5.0\Object Arts\Samples\Active X\Random. If I run RandomVBClient.exe with Dolphin running, it produces a run-time error 80040155, REGDB_E_IIDNOTREG. Without Dolphin running, it gives error 429, "Active X component can't create object." The COMClassFactory that is associated with it looks to get registered in COMClassFactory class>>registerAll along with mine, so that's probably why it almost works when Dolphin is running. It's probably not in the registry so that it could work properly without Dolphin running. I haven't try to register it for fear of messing everything up. Does everyone else have this example and does it work? Thanks. Keith Alcock Bill Schwab wrote: > > Keith, > > > it might have to do with the remaining problem: the only way that it works > is if I start up Dolphin > > manually. If Dolphin isn't running I get a CO_E_SERVER_EXEC_FAILURE error > in the out-of-proc case and > > REGDB_E_CLASSNOTREG error in the in-proc case. I still haven't figured > out how Windows knows when to use > > the proxy or how to find it and maybe that is related. Does this error > pattern ring a bell for anyone? > > The fact that it works when Dolphin is running has me wondering whether your > server is registered correctly. If you registered the class factory and > didn't subsequently unregister it, Dolphin will re-register it on startup. > Windows would then find it and not bother looking in the registry, at least > for the out of proc server. > > I've done only limited experimenting with DLL deployment and was never > concerned with deploying an EXE with the same interfaces. However, it seems > reasonable to be concerned about getting confused or conflicting data in the > registry. It might help to unregister the DLL or EXE before registering the > other??? > > I use a "bang on the box" approach to COM debugging. It usually goes > something like the following (early out on success): > > (1) check registration of marshaling DLL or type library > (2) look for zombie class factories and ensure that a valid one is > registered > (3) check registration of server > (4) Read Rogerson > (5) Ask Blair for help :) > > The zombie class factory thing might be unique to the way I work; I > explicitly register/unregister rather than leaving it to the base system, > and one common failure mode involves a couple of confused class factories > vs. one working class factory. One of my gizmos is particularly prone to > this problem. > > I have one auto-activated EXE server; the others register class factories > when they run. The auto-activated server just recently started taking > advantage of Automation types and a type library vs. a custom marshaling > DLL, and uses COMInterfaceImp>>register vs. a .REG file to create registry > entries - it wasn't broke, so I didn't try to fix it. So far, that all > seems to be working, but I'm installing and testing. > > Have a good one, > > Bill > > -- > Wilhelm K. Schwab, Ph.D. > [hidden email] |
Keith,
> In an attempt to debug this, I've set a breakpoint in COMClassFactory > class>>registerAll. When I start up Dolphin manually, this method runs and I get a > hard coded breakpoint dialog. My factory is present and everything works well. The > client can use the functions provided. However, when Dolphin starts up as a server > because my client makes a request instead of me starting it manually, I get no dialog > and the request fails. I don't know whether Dolphin starts up differently in the two > modes or whether a self halt works when Dolphin functions as a server, but it seems > odd that the breakpoint is not catching. It looks like #registerAll isn't called for DLLs; is that the problem? Given my fuzzy understanding of how COM DLLs work, it makes sense that they wouldn't register class factories. Some time ago, I got to "Ask Blair" in the algorirthm<g>, with the following response: > A COM server that worked even under 3.0 beta 2 is giving me trouble under > the release. Asking for a new interface pointer of the type it serves > results in the app's being auto activated, but, then COM feigns ignorance of > the interface. Sounds like a problem with the IID. In 3.0 the #initializeIID method is now obsolete. You'll need to reload the package into 3.0, reinitialize the IIDs (to overwrite the GUIDs allocated by the class builder when the interface classes were created), you can now remove the methods which send #iidString: (the iid is stored as the class guid in the filed-out representation, so now explicit initialization will be required any longer), and resave the package. If that doesn't work, try registering the development system as the COM server, and then set a breakpoint in an appropriate place in COMClassFactory. Although the system comes up in embedded mode, the breakpoint will work as normal, and you can debug away. You can also set breakpoints in any COM method implementation such as QueryInterface. ------------- The IID stuff is from the 3.0 release era, so it probably doesn't apply to you, but, a breakpoint in #queryInterface: sounds reasonable. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill Schwab wrote:
> > Keith, > > > In an attempt to debug this, I've set a breakpoint in COMClassFactory > > class>>registerAll. When I start up Dolphin manually, this method runs > and I get a > > hard coded breakpoint dialog. My factory is present and everything works > well. The > > client can use the functions provided. However, when Dolphin starts up as > a server > > because my client makes a request instead of me starting it manually, I > get no dialog > > and the request fails. I don't know whether Dolphin starts up differently > in the two > > modes or whether a self halt works when Dolphin functions as a server, but > it seems > > odd that the breakpoint is not catching. > > It looks like #registerAll isn't called for DLLs; is that the problem? > Given my fuzzy understanding of how COM DLLs work, it makes sense that they > wouldn't register class factories. > Bill, I should have made it clear that this was being done in an out-of-proc context. The Dolphin exe was (hopefully) running rather than the dll. As far as I know, executables do register the components--or are supposed to. Have you tried that random example at all? Thanks. |
Keith,
> I should have made it clear that this was being done in an out-of-proc context. The > Dolphin exe was (hopefully) running rather than the dll. As far as I know, executables > do register the components--or are supposed to. Class factories yes (assuming they are active when the image is saved or deployed); components, I think that's up to you to request. > Have you tried that random example at all? Yes, and it worked - not much help, I know. Blair had suggested it as an intermediate at one point to rule out problems. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Keith Alcock-3
"Keith Alcock" <[hidden email]> wrote in message
news:[hidden email]... > ... > Well, I had hoped to follow up this post with an announcement of complete success, but it's not quite > there yet. After spending a week meticulously reading the Rogerson book and implementing both client and > server in C++, I went back to Smalltalk with the proven IDL code and working client program and proxy DLL > and...wouldn't you know, it finally worked! I still haven't figured out where it went wrong before, but > it might have to do with the remaining problem: the only way that it works is if I start up Dolphin > manually. If Dolphin isn't running I get a CO_E_SERVER_EXEC_FAILURE error in the out-of-proc case and > REGDB_E_CLASSNOTREG error in the in-proc case. I still haven't figured out how Windows knows when to use > the proxy or how to find it and maybe that is related. Does this error pattern ring a bell for anyone? The fact that it is working if the Dolphin dev. env. is running shows that you have now overcome the marshalling obstacle. The remaining errors suggest simpler "registration" problems. > > The pertinent registry entries seem to be > > HKEY_CLASSES_ROOT > CLSID > {GUID} - value > LocalServer32 - Path\IPDolphin.dll > InProcServer32 - Path\Dolphin.exe > Image - Path\Professional.img > If these are really the registry entries you have, then the LocalServer32 and InProcServer32 entries would appear to be inverted for some reason. I would imagine, however, that this is just a transcription error in your posting and that the registry entries are actually correct, at least for development purposes. > It is interesting that Dolphin must use the image key to figure out which image to load. Hmmm, that gives me an inkling of a possible source of your problem. The Image value is only used by the generic In-proc stub (IPDolphin.DLL) to locate the image which implements the component (in this mode the specified development image will effectively run up inside the host/client executable). It would not be used for a deployed .EXE or .DLL COM server, since in that case the image is contained in the binary. As far as I recall the Image value is _not_ used by the standard development image launcher (dolphin.exe) when launching as a "local server". This would suggest that the launcher may not be finding the image, which (if so) is a bug caused by the removal of the infamous "load last used image" feature of D4. To prove this try either saving your image as 'dolphin.img' in the path from which Dolphin.exe is run, or (to avoid messing up a clean setup) copy dolphin.exe to another working directory and save a dolphin.img in there. Hope this helps Regards Blair |
Blair McGlashan wrote:
> > > > The pertinent registry entries seem to be > > > > HKEY_CLASSES_ROOT > > CLSID > > {GUID} - value > > LocalServer32 - Path\IPDolphin.dll > > InProcServer32 - Path\Dolphin.exe > > Image - Path\Professional.img > > > > If these are really the registry entries you have, then the LocalServer32 > and InProcServer32 entries would appear to be inverted for some reason. I > would imagine, however, that this is just a transcription error in your > posting and that the registry entries are actually correct, at least for > development purposes. > Blair, Indeed, this was a transcription error. > > It is interesting that Dolphin must use the image key to figure out which > image to load. > > Hmmm, that gives me an inkling of a possible source of your problem. The > Image value is only used by the generic In-proc stub (IPDolphin.DLL) to > locate the image which implements the component (in this mode the specified > development image will effectively run up inside the host/client > executable). It would not be used for a deployed .EXE or .DLL COM server, > since in that case the image is contained in the binary. As far as I recall > the Image value is _not_ used by the standard development image launcher > (dolphin.exe) when launching as a "local server". This would suggest that > the launcher may not be finding the image, which (if so) is a bug caused by > the removal of the infamous "load last used image" feature of D4. To prove > this try either saving your image as 'dolphin.img' in the path from which > Dolphin.exe is run, or (to avoid messing up a clean setup) copy dolphin.exe > to another working directory and save a dolphin.img in there. > > Hope this helps > > Regards > > Blair Doing this had no effect. Isn't the splash screen part of the image? It always shows, so I have assumed that some image has always been found. There is none called default.img or dolphin.img, so it seems like professional.img is the only possibility. Keith |
Free forum by Nabble | Edit this page |