views:

728

answers:

3

I recently developed an interop user control in .NET (Visual Studio 2008, project targetting .NET 2.0) to be used in a VB6 application. The assembly exposes 1 control, 1 class, and a few enums and structs. I developed it using C# translations of the Interop Forms Toolkit 2.0 project template found here. The assembly has a strong name and gets installed in the GAC and registered with regasm with the following script:

@"C:\gacutil.exe" /i "C:\Program Files\AppName\Control.dll" /f
@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe" "C:\Program Files\AppName\Control.dll" /tlb:"C:\Program Files\AppName\Control.tlb"

The Problem: When I compile the VB6 app on my machine, it will run just fine on any other machine (control installed, of course). However, when the app is compiled on a different machine, it will run on that machine, but not on any other machine. And when I say it doesn't run, I mean you try to run it and absolutely nothing happens.

I used OleView to examine the control on both my machine and the other machine, and all GUIDs are the same in the type information. The only difference was one had the line importlib("stdole2.tlb") and the other had importlib("STDOLE2.TLB").

My machine has: Visual Studio 6.0 sp6, VB6 interop user control templates, Windows SDK 6.0 and 6.0A, Visual Studio 2008 sp1. This machine is the one that works.

Coworkers machine: Visual Studio 6.0 sp6, Visual Studio 2005

Another machine: Visual Studio 6.0 sp6, Visual Studio 2008. 2008 was installed on this this morning and did not rectify the problem.

How do I get these other machines to compile the VB6 app correctly so that it runs on machines other than the one on which it was compiled?

(Put requests for more information in comments and I'll edit this to provide answers.)

Edits:

A suggestion was made regarding permissions in relation to registering the control. I'd like to clarify that the control seems to work well. I register it in the exact same way on the machine that works and the ones that don't. The problem manifests itself when the VB6 app that references the control is compiled on a machine other than my own.

I should also add that I had a small VB6 host app that had 1 form and the interop control and a couple buttons. This one does not exhibit the same problem as the main VB6 app.

Possibly a clue

If anybody is familiar with using OleView.exe, I think I may have discovered a clue. When I view the Type Libraries list, there is "OrderControl (Ver 0.1)" as well as "OrderControlCtl (Ver 0.1)". The first uses the GUID defined for the assembly and the path shows the OrderControl.tlb generated from using RegAsm.exe. The second has different GUIDs on the different machines and the path on mine is "C:\Program Files\Microsoft Visual Studio\VB98\vbc00305.oca", the path on the other machine is "C:\Program Files\Microsoft Visual Studio\VB98\mscoree.oca", and on the coworker's machine is "C:\windows\system32\mscoree.oca". Both mscoree.oca are the same size, but the vbc00305.oca on my machine is several KB smaller.

I looked again at the VB6 project's references. The references list both OrderControl and OrderControlCtl, but only OrderControlCtl is checked. OrderControl's location is the TLB file, but OrderControlCtl's location is the OCA file that's different on each station.

Dependency Walker

I ran profiles in DW for a version of the exe compiled on my machine and one compiled on our build machine (which won't run on mine). They diverge at the following 2 lines. Both have the first line, but the one that runs continues on with more calls/loads, while the one that does not run immediately begins detaching after the first line here:

GetProcAddress(0x7E720000 [SXS.DLL], "SxsOleAut32RedirectTypeLibrary") called from "OLEAUT32.DLL" at address 0x7712A637 and returned 0x7E746129.
GetProcAddress(0x7E720000 [SXS.DLL], "SxsOleAut32MapConfiguredClsidToReferenceClsid") called from "OLEAUT32.DLL" at address 0x7712A637 and returned 0x7E745C0D.
A: 

Try removing the user control from the form in your main VB6 app and re-adding it.

C-Pound Guru
That did not work.
Joel B Fant
A: 

Not sure, but I had also issues like that. Try using regasm with /codebase.

Stefan Egli
Where you using regasm alone when you were having problems and switched to using /codebase, or did you have it in the GAC and switched to using /codebase?
Joel B Fant
I did not use GAC but you can use it. In fact regasm warns you if you do not use GAC but the warning is only a problem if you try to have several versions of the assembly installed on the same machine. this again is something that does not go so well with COM
Stefan Egli
Fortunately there's just one version. The only difference between installing to GAC and using regasm /codebase (based on looking up regasm on msdn) is that with the latter, you have to keep the DLL around and keep it in that location.
Joel B Fant
The /codebase switch causes the tool to write the path to the assembly into the registry. COM cannot locate the DLL without that information; you cannot move COM DLLs around either, so that is not really a problem.
Stefan Egli
@Stefan: If you don't use /codebase and don't install to GAC, it should work if you make sure to copy the DLL to the same directory of any EXE using it.
Joel B Fant
ahh, yes that is of course also an option, just never was for me. as I did not know where my COM clients were located
Stefan Egli
+1  A: 

I've since discovered that it had to do with 3 particular methods on my control that were 'returning' (via ref parameter) structs. I ended up using a workaround involving returning classes instead of structs. But I'm still curious, so I asked a different question.

Joel B Fant