【问题标题】:C# Winforms Crashing from external function without exception, with exit code 40445582 (0x269268e)C# Winforms 无异常从外部函数崩溃,退出代码为 40445582 (0x269268e)
【发布时间】:2020-09-15 20:29:12
【问题描述】:

正如标题所示,我有一个用 C# .Net Framework 4.8 编写的 Winform;它从 mapi32.dll 调用 MAPISendMail 外部函数,在 Outlook 中为用户打开一个新的消息窗口,最初填充了收件人地址和消息(有时还有附件):

[DllImport("MAPI32.DLL")]
public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv);

注意:如果您知道有什么东西可以替代 MAPI 来实现所描述的用途,那将是惊人的。

无论出于何种原因,这会不时导致整个 winform 挂起一段时间,然后关闭。除了上述挂起之外,没有迹象表明这会发生,据我所知,也没有任何模式;我可以几个小时都没有遇到它。

此外,当这种情况发生时,不会捕获任何 try/catch 块。当然,我已经尝试捕捉标准的Exception,但也尝试捕捉RuntimeWrappedException,这也不会被触发:

try
{
    error = MAPIHelperInterop.MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, MAPI_DIALOG, 0);
}
catch (RuntimeWrappedException rwe)
{
    throw rwe.InnerException;
}
catch (Exception e)
{
    throw e;
}

出现问题的唯一迹象是 Debug 输出中的最后一行,指出“程序 'PROGRAMNAME' 已退出,代码为 40445582 (0x269268e)”。我已经用谷歌搜索了试图找到这段代码的含义,但一无所获。有没有人对这里可能发生的事情有任何见解,甚至可能有一种方法可以让我捕捉到这个错误以防止表单关闭?

【问题讨论】:

  • @CHowell 不幸的是,似乎没有任何方法可以处理附件,因为它被认为存在安全风险。 MAPI 是一个已弃用的 API,您应该尽可能避免使用它,因为它可能会在将来的某个时候完全消失。我很欣赏如果您的用户习惯了此功能,这对他们来说不太可能有问题,但是让他们知道您正在删除该功能,然后将其删除,这比等待 Microsoft 删除它然后再删除它是一个更好的解决方案惊慌失措。
  • 使用 Outlook 互操作的最大问题是它可能无法与 Outlook 以外的任何电子邮件客户端一起使用,而 MAPI 可以与任何系统默认电子邮件客户端一起使用(与 MAPI 一样) .如果您只关心 Outlook,那么 interop 绝对是最佳选择 - 只需确保使用官方 NuGet 包 (nuget.org/packages/Microsoft.Office.Interop.Outlook) 而不是尝试将您的应用程序硬链接到 interop DLL。 API 肯定没有太大变化,所以你找到的答案应该还是不错的。
  • 在这种情况下,我很幸运我知道我的所有用户都在使用 Outlook!感谢您的帮助。如果我的声望 +15,我会支持你和 @HansPassant。

标签: c# .net winforms dllimport exit-code


【解决方案1】:

我基本上问错了问题。感谢 Hans Passant 和 Ian Kemp 指出 MAPI is long deprecated and should be avoided

感谢this SO question,我使用了Microsoft.Office.Interop.Outlook,并制作了一个非常简单的包装类:

    public class OutlookEmail
    {
        public OutlookEmail() { }
        public OutlookEmail(params string[] toAddrs)
        {
            To.AddRange(toAddrs);
        }
        private Application OApp = new Application();
        public List<string> To { get; set; } = new List<string>();
        public string Subject { get; set; }
        public string Body { get; set; }
        public List<string> Attachments { get; set; } = new List<string>();
        public void ShowDialog()
        {
            _MailItem oMailItem = (_MailItem)OApp.CreateItem(OlItemType.olMailItem);
            oMailItem.To = string.Join("; ", To);
            // body, bcc etc...
            oMailItem.Subject = Subject;
            oMailItem.Body = Body;
            if(Attachments != null)
            {
                foreach (string path in Attachments)
                {
                    oMailItem.Attachments.Add(path);
                }
            }

            oMailItem.Display(true);
        }
    }

注意:这仅适用于 Outlook;幸运的是,我的所有用户都使用 Outlook。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    相关资源
    最近更新 更多