5

I have the following COM object installed on one of our servers that I need to rewrite...some legacy code uses the object as follows:

Set oEmail = CreateObject("SSDSCommunicator.EmailClass")
oEmail.Send(szFrom, szRecipients, szSubject, szEmailBody, SMTPServer, szErr, "", , , , True)

I have followed the example in this answer but I'm struggling to register the COM component.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mail;
using System.Runtime.InteropServices;


namespace SSDSCommunicator
{

    [InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("DB38A91C-9EB6-4472-9A49-40722431E096")]
    public interface IEmailClass
    {
        void launch();
        bool Send(string szFrom, string szTo, string szSubject, string szMessage, string szSMTPServer, ref object szError, string szAttachments = "", string szReplyTo = "", string szCC = "", string szBCC = "", bool bHTMLBody = false);
    }

    [ClassInterface(ClassInterfaceType.None), Guid("A00C16DA-1791-4A3A-8D16-4765A9FAD060"), ProgId("SSDSCommunicator.EmailClass")]
    public class EmailClass : IEmailClass
    {
        private string path = null;

        public void launch()
        {
            Console.WriteLine("I launch scripts for a living.");

        }

        public bool Send(string szFrom, string szTo, string szSubject, string szMessage, string szSMTPServer, ref object szError, string szAttachments = "", string szReplyTo = "", string szCC = "", string szBCC = "",    bool bHTMLBody = false)
        {
    ...
        }

    }
}

The project builds successfully. How do I register the dll as a COM object so that the the old VB6 code will work?

I have ticked the register for COM interop and Make the assembly COM visible in the project settings.

I've had no luck with regsvr32 (no entry point found) or regasm...

The COM object looks like this on the old server:

enter image description here

Edit

Should I be able to see the COM object in component services after running the regasm command?

regasm C:\...\SSDSCommunicator.dll /CodeBase
Community
  • 1
  • 1
woggles
  • 7,444
  • 12
  • 70
  • 130
  • you mention regasm, but did you use it like this: "regasm.exe /codebase youlib.dll"? (the codebase parameter is important) – Stefan Egli Nov 15 '11 at 14:34
  • Did you set the assembly attribute [assembly: ComVisible(true)] for you assembly ? – user957902 Nov 15 '11 at 14:55
  • @StefanEgli I did. A TLB file is then produced. I'm not too sure of the next steps - when I create a vbscript file with this code `set obj = createObject("SSDSCommunicator.EmailClass")` I get an ActiveX component can't create object 800A01AD error. I also cant see the object in the Component explorer like in my screenshot above – woggles Nov 15 '11 at 14:58
  • Are you on 32bit or 64bit OS ? – user957902 Nov 15 '11 at 15:24
  • @user957902 64bit windows 7 - final install will be on 64bit server 2008 – woggles Nov 15 '11 at 15:38
  • OK, there are two COM domains on 64 bit systems, one for 32 bit objects and one for 64 bit objects. What is your target platform for your .Net assemblies ? – user957902 Nov 15 '11 at 16:11
  • @user957902 my target platform was any cpu. If I try to build using x64 I get an error with regasm saying the dll is not a valid .NET assembly. If I build targeting x86 then I still can't create the object after using regasm. Should I be able to see the COM object in component services after running the regasm command? – woggles Nov 16 '11 at 06:39
  • A COM object is not visible in Component services by default. To do that, you need to let your class inherit from ServicedComponent and use regsvcs to register it, instead of regasm. Furthermore, if your object is being used from a client machine (through a COM proxy), you will need to distribute a new proxy. – GTG Nov 16 '11 at 07:49
  • @GTG thanks - this will only be used from the (web) server that it is installed on so there will be no need for a proxy – woggles Nov 16 '11 at 08:08

2 Answers2

1

OK sweet...found the answer to this thanks to user957902 and GTG (write some answers below if you want points):

  • Built the solution targeting x86
  • Signed the assembly using an .snk file
  • Inherited ServicedComponent
  • Manually added the SSDSCommunicator component in component services and then added the dll as a component

Final code below:

 using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web.Mail;
    using System.Runtime.InteropServices;
    using System.EnterpriseServices;


    namespace SSDSCommunicator
    {

        [InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("DB38A91C-9EB6-4472-9A49-40722431E096")]
        public interface IEmailClass
        {           
            bool Send(string szFrom, string szTo, string szSubject, string szMessage, string szSMTPServer, ref object szError, string szAttachments = "", string szReplyTo = "", string szCC = "", string szBCC = "", bool bHTMLBody = false);
        }

        [ClassInterface(ClassInterfaceType.None), Guid("A00C16DA-1791-4A3A-8D16-4765A9FAD060"), ProgId("SSDSCommunicator.EmailClass")]
        public class EmailClass : ServicedComponent, IEmailClass
        {
            private string path = null;           

            public bool Send(string szFrom, string szTo, string szSubject, string szMessage, string szSMTPServer, ref object szError, string szAttachments = "", string szReplyTo = "", string szCC = "", string szBCC = "",    bool bHTMLBody = false)
 {...
}

        }
    }
woggles
  • 7,444
  • 12
  • 70
  • 130
1

There are two COM domains on a 64 bit system. One for 32 bit COM objects and the other 64 bit COM objects. If your .Net assemblies are ANY_CPU then by default its going to start up as a 64 bit process on a 64 bit system. If your COM object is regested as only 32 bit then the 64 bit process can't see it. The reverse is also ture, if the COM object is regested only as 64 bit then a 32 bit process can't see it.

user957902
  • 3,010
  • 14
  • 18