MAPI和托管代码的经验?

时间:2020-03-05 18:38:16  来源:igfitidea点击:

正式不支持在托管代码中使用MAPI函数。显然,MAPI使用其自己的内存管理,并且在托管代码内崩溃和刻录(请参见此处和此处)

我要做的就是启动带有主题,正文和一个或者多个附件的默认电子邮件客户端。

因此,我一直在研究MAPISendDocuments,它似乎可以正常工作。但是我无法鼓起勇气在生产代码中实际使用该功能。

有人经常使用此功能吗?你有恐怖故事吗?

PS。不,我不会使用命令行参数对附件执行ShellExecute Outlook.exe。

PPS。附件支持是必需的,因此Mailto:解决方案对我而言并不适合。

解决方案

回答

调用过程。从Mailto:协议开始(如下所示)将为我们提供基本功能,但没有附件。

Process.Start("mailto:[email protected]?subject=TestCode&Body=Test Text");

我们可以使用附件路径执行此方法,但是此选项仅适用于某些旧版本的Outlook(例如98)。我认为这是由于潜在的安全风险。

如果有人使用Outlook.exe,它将在Outlook 2003(和2007年取决于设置)下给出安全警告。

回答

我们应该能够制作一个非托管的DLL,以使用MAPI执行所需的操作,然后从托管代码中调用该DLL。我不会写一个直接的MAPI包装器,而是可以执行非托管DLL中包含的MAPI所需的所有功能的东西。这可能是从托管代码使用MAPI的最安全方法。

回答

我们还可以使用托管代码支持的Outlook Redemption;我不确定是否可以简单地替换MAPISendDocuments,但是如果我们有疑问,Dmitry会为我们提供帮助。

至于"崩溃和烧伤",这是MS支持人员的另一句话,在这里

It's the sort of thing that'll mostly work. It'll work while you're writing it. Then it'll work while you're testing it. It'll work while your customer is evaluating it. Then as soon as the customer deploys it - BAM! That's when it'll decide to start having problems. And Microsoft ain't gonna help you with it, since we told you not to do it in the first place. :)

回答

我已经使用MAPISendMail函数和一些内部类来完成此操作,以包装一些其他与MAPI相关的结构。只要这是唯一的用途,就可以安全地进行操作,尽管这并非一件简单的事,但它需要密切注意各种非托管数据类型以及内存分配/取消分配和GC。尽管仍然不支持它,但我仍在生产代码中使用了它(尽管尚未交付)。

当我问Matt Stehle这件事时,我收到的答复是:

I really don't know of a much better way to do this and any issues you ran into here would be probably reproducible in a supported scenario (i.e. VB6 or unmanaged C++).  Just know that if you ever ran into a scenario were an issue was caused specifically by this function being called from .NET that we wouldn't have any other recommendation for you then to not use .NET.

使用它并不完全是一种祝福,但是也没有说还有其他选择可以从托管代码中实际执行此操作。

回答

有一个单独的帮助程序EXE,它可以执行所需的命令行参数(或者通过管道连接到其StandardInput),并从主应用程序中调用它。这样可以将MAPI内容保留在主应用程序的处理空间之外。好的,我们仍然在混合MAPI和.NET,但是过程非常短暂。假定MAPI和CLR开始导致运行时间更长的进程出现问题。

我们使用Dmitry Streblechenko精湛的Redemption Data Objects库,该库允许我们在JScript中编写此类"填充"代码并进行调用,从而将CLR和MAPI世界保持在单独的进程中,但以受支持的方式。

@克里斯·弗尼尔(re。编写非托管DLL。这将不起作用,因为问题是在同一过程中混合了MAPI和托管代码。

回答

对于具有MAPI经验的人来说,他们花费更少的时间来编写代码以完成非托管代码(读为:普通C ++)中想要的事情,而不是键入这篇文章并阅读响应(没有冒犯)。

我们很幸运,所需的功能有限。我们只需要一个简单的C ++实用程序,即可在命令行上获取所需的参数并发出正确的MAPI调用。然后,从托管代码中使用所有此实用程序,就像执行任何其他过程一样。

高温超导

回答

MAPISendDocuments已过时,可能已删除。
我们应该改用MAPISendMail。
请参阅简单的MAPI

回答

以下代码不使用MAPI,但确实打开带有任意附件的"撰写邮件"窗口。

(实际上,它完全未经测试,但我在一个我认为可以正常工作的应用程序中进行了挖掘)

using Microsoft.Office;
using Microsoft.Office.Core;

...

Outlook.Application outlook = new Outlook.Application();
Outlook.MailItem mail = (Outlook.MailItem) outlook.CreateItem(Outlook.OlItemType.olMailItem);

mail.BodyFormat = Outlook.OlBodyFormat.olFormatRichText;
mail.HTMLBody = "stuff";
mail.Subject = "more stuff";
string file = File.ReadAllBytes(...);
mail.Attachments.Add(file, Outlook.OlAttachmentType.olByValue, 1, file)

mail.Display(false);