C# Winforms 无异常从外部函数崩溃,退出代码为 40445582 (0x269268e)

Posted

技术标签:

【中文标题】C# Winforms 无异常从外部函数崩溃,退出代码为 40445582 (0x269268e)【英文标题】:C# Winforms Crashing from external function without exception, with exit code 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)”。我已经用谷歌搜索了试图找到这段代码的含义,但一无所获。有没有人对这里可能发生的事情有任何见解,甚至可能有一种方法可以让我捕捉到这个错误以防止表单关闭?

【问题讨论】:

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

【讨论】:

以上是关于C# Winforms 无异常从外部函数崩溃,退出代码为 40445582 (0x269268e)的主要内容,如果未能解决你的问题,请参考以下文章

删除临时文件时 C# 应用程序无异常退出

程序崩溃优雅退出之-SetUnhandledExceptionFilter

程序崩溃优雅退出之-SetUnhandledExceptionFilter

从 C# 崩溃异常 中研究 页堆 布局

我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃

忽略在 C# .NET 中抛出的特定异常