Documentation on using Dolphin as COM server

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

Documentation on using Dolphin as COM server

Keith Alcock-3
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Blair McGlashan
"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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Louis Sumberg-2
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Blair McGlashan
In reply to this post by Keith Alcock-3
Keith

What version of Dolphin are you using?

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Bill Schwab-2
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]


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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.


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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.
>


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Howard Ding-2
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?


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Bill Schwab-2
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]


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Blair McGlashan
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Bill Schwab-2
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]


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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]


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Bill Schwab-2
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]


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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.


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Bill Schwab
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]


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Blair McGlashan
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


Reply | Threaded
Open this post in threaded view
|

Re: Documentation on using Dolphin as COM server

Keith Alcock-3
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


12