Reputation: 1552
I am creating a COM server .dll in C# (.NET 3.0 - external requirement). Some clients work well with it but others do not. Specifically, I'm having problems getting VBScript to like it.
There are two primary components:
a. an interface
b. an implementation object
they both have their own GUID's. The implementation class EXPLICITLY implements the interface.
The 'Assembly Information' dialog check box 'Make assembly COM-Visible' is checked.
The 'Build' dialog check box 'Register for COM interop' is also checked.
I also signed the assembly, created a Strong Name Key.
In desperation, I added the System.EnterpriseServices.ServicedComponent
assembly:
[Guid( "0135bc5c-b248-444c-94b9-b0b4577f5a1b" )]
public class TwoPays : ServicedComponent, ITwoPays
{
void ITwoPays.TestConnect()
{
...
[Guid( "0135bc5c-b248-444c-94b9-b0b4577f5a1a" )]
public interface ITwoPays
{
I also ran regsvcs.exe
.
RegSvcs.exe LandCORC.dll Microsoft (R) .NET Framework Services Installation Utility Version 2.0.50727.5483 Copyright (c) Microsoft Corporation. All rights reserved.
Which failed with:
WARNING: The assembly does not declare an ApplicationAccessControl Attribute. Application security will be enabled by default.
Installed Assembly:
Assembly: C:\Source\LandCORC\bin\Release\LandCORC.dll
Application: LandcORC
TypeLib: C:\Source\LandCORC\bin\Release\LandCORC.tlb
Since I also don't know anything about Application security, I'm not sure if the warning message from RegSvcs.exe
is important.
So I've been using VbsEdit to test it. Before I added the ServicedComponent
and ran RegSvcs.exe
, it would die on the Set objXL = CreateObject("LandCORC.TwoPays")
statement.
Now that completes but when I try to call TestConnect
it says that objXL
is an invalid pointer, for example:
Dim objXL
Set objXL = CreateObject("LandCORC.TwoPays")
objXL.TestConnect
Adding the reference for VbsEdit:
Prog ID: LandCORC.TowPays
TypeLib path: C:\Source\LandCORC\bin\Release\LandCORC.tlb
GUID: {0135BC5C-B248-444C-94B9-B0B4577F5A1B}
But if I change the VbsEdit reference to use the interface GUID instead, then the auto complete for objXL
will show the correct list of methods but then when it executes that I get 'Object doesn't support this property or method: TestConnect' instead.
I don't know what I need to complete the puzzle.
NEW INFORMATION Based on Kev's answer, I have corrected the interface and class definitions.
[Guid( "0135bc5c-b248-444c-94b9-b0b4577f5a1a" )]
[InterfaceType( ComInterfaceType.InterfaceIsDual )]
[ComVisible( true )]
public interface ITwoPays
{
[DispId( 1 )]
void TestConnect();
[DispId( 2 )]
void Terminate();
[Guid( "0135bc5c-b248-444c-94b9-b0b4577f5a1b" )]
[ClassInterface( ClassInterfaceType.None )]
[ComVisible( true )]
public class TwoPays : ITwoPays
{
[ComVisible( true )]
public void TestConnect()
{
LogInformationMessage( "TestConnect." );
}
[ComVisible( true )]
public void Terminate()
{
And running RegAsm /codebase /register /tlb comes back clean as does running the gacutil -i which states Assembly successfully added to the cache
Upvotes: 3
Views: 922
Reputation: 119816
This is from a project where I had a similar requirement, an InProc COM wrapped .NET component visible to VBScript and Classic ASP (as in IDispatch
friendly in COM parlance).
I've renamed the interface, class and methods but you should get the idea.
Declare our interface:
[Guid("0B201484-E388-45eb-9AB8-A6AE1E197AAB")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface IThingy
{
[DispId(1)]
int DoThing1(string name, int age);
[DispId(2)]
string DoThing2(int id);
[DispId(3)]
bool DoThing3(string address);
}
Implementation:
[Guid("68FAB6AC-9923-425a-85F2-59B50552A5C1")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Thingy: IThingy
{
[ComVisible(true)]
public int DoThing1(string name, int age)
{
// ....
}
[ComVisible(true)]
public string DoThing2(int id)
{
// ....
}
[ComVisible(true)]
public bool DoThing3(string address)
{
// ....
}
}
I also had to generate an assembly key file, this is because COM wrapped .NET assemblies need to be "strongly named" (I vaguely remember - it's been ten years since I wrote this code).
Next I regasm'd the assembly which does all the fun COM wiring in the registry:
regasm.exe COMExample.Fun.dll /register /codebase /tlb
And then chucked it in the GAC:
gacutil.exe -i COMExample.Fun.dll
To uninstall:
gacutil.exe -u COMExample.Fun.dll,Version=1.0.0.0
regasm.exe COMExample.Fun.dll /unregister /tlb
Get rid of the System.EnterpriseServices
and ServicedComponent
stuff. You only need that if you're going run up an out of process server in COM+ and need the COM+ transactional infrastructure etc.
Upvotes: 3