You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C#代码获取Windows默认应用设置中的默认邮件客户端?

解决C# WinForms获取Windows默认邮件客户端及mailto崩溃问题

一、获取正确的默认邮件客户端

Windows 10及以上系统中,默认邮件客户端的关联信息不再仅通过HKEY_CURRENT_USER\SOFTWARE\Clients\Mail注册表项存储,直接读取该路径会出现和系统设置不符的情况。推荐使用Windows系统提供的AssocQueryString API来获取准确的默认关联信息,这是系统查询协议/文件关联的官方方法。

C#实现代码

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public static class DefaultMailClientHelper
{
    // 定义AssocQueryString所需的枚举
    private enum AssocF
    {
        IsProtocol = 0x00001000
    }

    private enum AssocStr
    {
        Executable = 2,       // 获取客户端可执行文件路径
        FriendlyAppName = 3   // 获取客户端友好名称
    }

    // 导入shlwapi.dll中的AssocQueryString方法
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern uint AssocQueryString(
        AssocF flags,
        AssocStr str,
        string protocol,
        string extra,
        [Out] StringBuilder output,
        ref uint outputSize);

    /// <summary>
    /// 获取默认邮件客户端的可执行文件路径
    /// </summary>
    /// <returns>路径字符串,无默认客户端则返回null</returns>
    public static string GetDefaultMailClientPath()
    {
        uint bufferSize = 0;
        // 第一次调用获取所需缓冲区大小
        AssocQueryString(AssocF.IsProtocol, AssocStr.Executable, "mailto:", null, null, ref bufferSize);

        if (bufferSize == 0)
            return null;

        StringBuilder buffer = new StringBuilder((int)bufferSize);
        uint result = AssocQueryString(AssocF.IsProtocol, AssocStr.Executable, "mailto:", null, buffer, ref bufferSize);

        return result == 0 ? buffer.ToString() : null;
    }

    /// <summary>
    /// 获取默认邮件客户端的友好名称
    /// </summary>
    /// <returns>名称字符串,无默认客户端则返回null</returns>
    public static string GetDefaultMailClientName()
    {
        uint bufferSize = 0;
        AssocQueryString(AssocF.IsProtocol, AssocStr.FriendlyAppName, "mailto:", null, null, ref bufferSize);

        if (bufferSize == 0)
            return null;

        StringBuilder buffer = new StringBuilder((int)bufferSize);
        uint result = AssocQueryString(AssocF.IsProtocol, AssocStr.FriendlyAppName, "mailto:", null, buffer, ref bufferSize);

        return result == 0 ? buffer.ToString() : null;
    }
}

使用示例

// 获取默认邮件客户端信息
string clientPath = DefaultMailClientHelper.GetDefaultMailClientPath();
string clientName = DefaultMailClientHelper.GetDefaultMailClientName();

if (string.IsNullOrEmpty(clientPath))
{
    MessageBox.Show("未检测到默认邮件客户端,请安装后重试。");
}
else
{
    MessageBox.Show($"当前默认邮件客户端:{clientName}\n路径:{clientPath}");
    // 此处可执行mailto操作
}

二、解决mailto协议调用崩溃问题

当系统无邮件客户端且无微软商店时,直接调用Process.Start("mailto:...")会触发未捕获的异常导致应用崩溃。解决方式是提前检查默认客户端,并在调用时捕获异常:

try
{
    string clientPath = DefaultMailClientHelper.GetDefaultMailClientPath();
    if (string.IsNullOrEmpty(clientPath))
    {
        MessageBox.Show("未检测到默认邮件客户端,请安装邮件客户端后再尝试发送邮件。");
        return;
    }

    // 调用mailto协议
    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("mailto:recipient@example.com?subject=Test&body=Hello")
    {
        UseShellExecute = true
    };
    System.Diagnostics.Process.Start(startInfo);
}
catch (System.ComponentModel.Win32Exception ex)
{
    // 捕获无关联应用的异常
    MessageBox.Show($"无法启动邮件客户端:{ex.Message}");
}
catch (Exception ex)
{
    // 处理其他异常
    MessageBox.Show($"发送邮件失败:{ex.Message}");
}

说明

  • AssocQueryString API会自动读取系统当前的默认应用设置,结果与Windows设置中的默认邮件客户端完全一致。
  • 提前检查+异常捕获的组合可以彻底避免无客户端场景下的应用崩溃问题。

内容的提问来源于stack exchange,提问作者Kha Minh Ho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:05:22