0
votes

I have a .Net COM server that has a method that takes a message and a delay as parameters. After the delay, it fires an event sending the message back to the client.

It works with .Net and VB6 clients.

In order to get the COM event to bind in FoxPro, you have to create a class that implements the event interface in foxpro and wire it up, as described here: http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

I have such a class:

DEFINE CLASS ComEventHandler AS session OLEPUBLIC
  IMPLEMENTS IComServerEvents IN "PcaTest.ComServer"
  * "C:\ComTest\PCATest.tlb"

  PROCEDURE IComServerEvents_TimerExpired(message AS STRING) AS VOID
  * add user code here
  ?message
  ENDPROC
ENDDEFINE

And the code to wire this up:

loMM = CREATEOBJECT("PcaTest.ComServer")
loEvents = CREATEOBJECT("ComEventHandler")

EventHandler(lomm, loevents)

When I run this code, I get Type Library PcaTest.ComServer not found. However, it works as expected if I change the implements line to:

IMPLEMENTS IComServerEvents IN "C:\ComTest\PCATest.tlb"

I can't hard-code the location of the tlb.

The line "CREATEOBJECT("PcaTest.ComServer")" works fine, actually, and if I don't try to instantiate a ComEventHandler object, that COM object is instantiated and I can call its methods and access its properties. The event handler class is (mostly) only working when I feed it the .tlb and not the progId.

The .Net COM server is registered in the GAC. I've tried regasm with and without /codebase and with and without /tlb or /tlb:filename.tlb

I did have this working in testing at one point, or so it seemed. I am unable to duplicate those results now, but when I had it working I had used /codebase and /tlb:filename.tlb.

2

2 Answers

0
votes

You mention that you can't hard-code the location, i was wondering if you could put it into a table, select it from the table and then use something like this

tlbLocation (field that contains path)

IMPLEMENTS IComServerEvents IN (tlbLocation)

I do similar path specifications with some of my apps

0
votes

I hate to answer my own question. Again. But I got it.

Answer: using regasm /codebase when the assembly is registered in the GAC makes it not work. My problem was that if I did regasm before installing the assembly in the GAC, it would work, but if the assembly was registered in the GAC first, or if it was registered in the GAC and regasm is called at a later time, FoxPro gets confused.

Consuming a .Net COM server's events in FoxPro absolutely requires:

  • assembly registered for COM (progId and ClsId), probably by regasm
  • /codebase flag on regasm that adds something like this into the registry:

    [HKEY_CLASSES_ROOT\CLSID\{A2DA47BD-15E8-48E3-BA54-4B1CED2D3C01}\InprocServer32]
    @="mscoree.dll"
    "CodeBase"="file:///C:/MACsWave/PCATest/pcatest.dll"
    

    Codebase is required, even though the assembly ought to be accessible from the GAC. /codebase is not required for VB6 clients, for example

  • /tlb flag to register typelib. /tlb:"filename" is not required.

Because the /codebase flag is used, registering the assembly in the GAC is not needed.

If you do add the assembly to the GAC and subsequently call regasm /codebase, you get this in the registry:

[HKEY_CLASSES_ROOT\CLSID\{A2DA47BD-15E8-48E3-BA54-4B1CED2D3C01}\InprocServer32]
@="mscoree.dll"
"CodeBase"="file:///C:/WINDOWS/assembly/GAC_32/PCATest/1.1.0.0__325ac2fec08eafa8/PCATest.dll"

I wonder whether perhaps FoxPro is looking for the tlb file in the same directory as the dll, but finds there is no .tlb in the GAC. Or something...

In any case, problem solved.