5

I have a Unit Test project that makes use of Interop.ADODB. Here is the code:

public CDO.Message ReadMessage(string emlFileName)
{
    if (string.IsNullOrEmpty(emlFileName)) return null;
    CDO.Message msg = new CDO.MessageClass();
    ADODB.Stream stream = new ADODB.StreamClass();
    stream.Open(Type.Missing,
        ADODB.ConnectModeEnum.adModeUnknown,
        ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified, string.Empty, string.Empty);
    stream.LoadFromFile(emlFileName);
    stream.Flush();
    msg.DataSource.OpenObject(stream, "_Stream");
    msg.DataSource.Save();
    return msg;
}

The problem is that I converted this project to .NET Core. I cannot figure out how to import the COM libraries that I need to make this method works. The ones that I need are Interop.ADODB and Interop.CDO.

All this method does is takes an email file and converts to the object so that I may read the values out of it and then compare to the email that was sent. Really a simple unit test to validate email contents.

Is there a way for me to import COM objects or is there a library that replaced CDO.Message that I am suppose to use now?

Simon
  • 2,643
  • 3
  • 40
  • 61
Bagzli
  • 6,254
  • 17
  • 80
  • 163
  • if you are you using VS2017 then there is an option to add a COM library by "Add reference" – Niladri Oct 21 '17 at 17:42
  • @Niladri I was looking for something like that but I don't see it. I am using VS2017 Community. The only things listed under "Add Reference" Are Projects and Shared Projects. That is how I use to do it on my old MVC5 projects. This is now a core project and it seems very different. – Bagzli Oct 21 '17 at 17:43
  • but i think it's still there in professional and ultimate not sure about community. There is an option for assembly also "dependencies -> add reference-> assembly " – Niladri Oct 21 '17 at 17:48
  • 1
    In general, one of the points of "DotNet Core" frameworks is to enable writing portable apps which you can later host also on Azure/Docker/Linux/etc. Using COM API prevents that, since you need Windows by definition and often you also need some special local components to be installed, which prevents cloud hosting, and so on. If I googled it properly, emlFiles seem like emails and CDO.Message indicates Exchange server? Are you sure that this set of APIs is still OK to use? I searched a bit and I think Exchange provides REST API, I think it be much more convenient for you in the long term. – quetzalcoatl Oct 21 '17 at 17:50
  • 2
    and if you don't need portability/multiplatform hosting, why bother with aspnetcore? do it on normal aspnet. If I recall roadmaps well, both will be supported in long term, so limiting yourself to Core when you don't need it seems unwise. – quetzalcoatl Oct 21 '17 at 17:52
  • 1
    yes bad news and good news for you http://weblogs.foxite.com/joel_leach/2016/10/19/com-interop-with-net-core/ – Niladri Oct 21 '17 at 17:54
  • There is a bug for ASP.NET Core projects. You can read more on my post: https://www.mobilize.net/blog/mauricios-blog-redux . In general the ASP.NET Core projects will have issues. A quick workaround is to create a .NET Core Class Library and add the COM references, you can then build and take the Interop.XXX files to a Libs folder. And add the reference to those assemblies. – orellabac Jul 28 '20 at 20:22

1 Answers1

10

It's unadvisable to access COM objects from .NET Core, as .NET Core applications are designed to be platform independent, and COM objects such as ADODB.Stream and CDO.Message are specific to Windows.

However, it is indeed possible - if you don't mind late binding and weak typing.

dynamic msg = Activator.CreateInstance(Type.GetTypeFromProgID("CDO.Message", true));

...

dynamic stream = Activator.CreateInstance(Type.GetTypeFromProgID("ADODB.Stream", true));

etc.

This works on .NET Core 2.0, when running on Windows. Apparently, according to this article, it was not possible on previous versions.

Still, it would be better to re-write your method using managed platform-neutral code.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Do you know of any libraries that Core supports and it will read an eml file and return it as an object? – Bagzli Oct 21 '17 at 18:01
  • I've just read that `Type.GetTypeFromProgID` doesn't work on 1.0 and 1.1, either it's missing, or throws platform-not-supported - but I just read about it, not tried myself. Anyways, just in case Bojan skips my comment on the question, I strongly believe that Exchange exposes new, non-COM APIs that can do the same. Worth checking and dropping usage of COM if possible, but of course it's some extra work and new code to write, which may be hard to force through project management if we have legacy COM code that "works fine since all those years" and we "just need it on Core". – quetzalcoatl Oct 21 '17 at 18:01
  • @quetzalcoatl I have seen your comment, I was just googling and trying to figure out what you mean by "Exchange" I assume its a set of libraries? – Bagzli Oct 21 '17 at 18:03
  • @Bojan: `object` is ANYTHING. A string is an object. If you request reading specific file format, and you want to use it for some specific use, you have to define what you expect to get. By saying "and get an object" you say nothing - and I can answer: Use `System.IO.File.ReadAllText` and you will get a string, which is an object. However, I doubt it will really help you. – quetzalcoatl Oct 21 '17 at 18:04
  • @quetzalcoatl What I meant was the Interop.CDO.Message is basically an object with properties that of an email. I was just asking if there is a library that pretty much does that, takes an eml file and converts to an object that has properties of that email such as Subject, Message, Cc, Bcc, etc... – Bagzli Oct 21 '17 at 18:06
  • @Bojan: Microsoft Exchange Server. https://msdn.microsoft.com/en-us/library/ms526591(v=exchg.10).aspx and note that small "Exchange Server 2003" note below the title. Your question worries me. How did you end up using CDO.Message if you don't know what Exchange is? DId you google it up as well? Are you just trying to send emails from aspnet core? – quetzalcoatl Oct 21 '17 at 18:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157198/discussion-between-bojan-and-quetzalcoatl). – Bagzli Oct 21 '17 at 18:08
  • If I guessed well, then read this: https://dotnetcoretutorials.com/2017/01/11/sending-receiving-email-net-core/ and try using [MailKit nuget](https://github.com/jstedfast/MailKit#using-mailkit) - it works really well and is quite easy. – quetzalcoatl Oct 21 '17 at 18:10
  • @quetzalcoatl - Yes, that article is correct that it is not implemented on .net core 1.0 or 1.1. However, it is indeed implemented and working on .net core 2.0. – Matt Johnson-Pint Oct 21 '17 at 18:11
  • 1
    @MattJohnson: whooo, thanks that's nice to know @Bojan: if you'd like to try mailkit, https://github.com/jstedfast/MailKit/blob/master/FAQ.md and `var message = MimeMessage.Load ("message.eml");` or `Load(emlFileStream)` – quetzalcoatl Oct 21 '17 at 18:13
  • Agreed. Mailkit is a much better way to go. Parsing example is here: http://www.mimekit.net/docs/html/Parsing-Messages.htm – Matt Johnson-Pint Oct 21 '17 at 18:19