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

如何通过VSTO可靠检测Outlook中新增的账户或存储?

可靠检测Outlook新增账户/存储的解决方案

1. 修复StoreAdd事件失效问题:保持对象生命周期

你之前的代码中Stores是局部变量,方法执行完成后会被垃圾回收,导致事件订阅失效。需要将其声明为类级字段,确保持续被引用:

private Outlook.Stores _outlookStores;

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    Outlook.NameSpace ns = Application.Session;
    // 保存为类级变量,避免被GC回收
    _outlookStores = ns.Stores;
    _outlookStores.StoreAdd += Stores_StoreAdd;
    _outlookStores.StoreRemove += Stores_StoreRemove;
}

private void Stores_StoreAdd(Outlook.Store Store)
{
    // 处理新增存储逻辑
}

private void Stores_StoreRemove(Outlook.Store Store)
{
    // 处理删除存储逻辑(可选)
}

2. 直接使用AccountAdded事件(Exchange账户优先)

Outlook的Application对象提供了AccountAdded事件,专门针对账户新增操作,比StoreAdd更直接适配Exchange场景:

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    Application.AccountAdded += Application_AccountAdded;
}

private void Application_AccountAdded(Outlook.Account Account)
{
    // 账户新增触发,若需要关联到对应Store,可延迟后遍历查找
    Task.Delay(2000).ContinueWith(_ => 
    {
        this.Invoke(new Action(() => 
        {
            foreach (Outlook.Store store in Application.Session.Stores)
            {
                if (store.Account == Account)
                {
                    // 找到对应存储,执行操作
                    break;
                }
            }
        }));
    });
}

注:Exchange账户配置是异步过程,AccountAdded触发时Store可能未同步完成,延迟操作可提高可靠性。

3. 改进轮询方案(兜底方案)

之前的轮询仅对比Count不准确,改为遍历存储名称列表,精准捕获新增项:

private List<string> _existingStoreNames;
private CancellationTokenSource _pollingCts;

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    // 初始化现有存储名称列表
    _existingStoreNames = Application.Session.Stores.Cast<Outlook.Store>()
                                .Select(s => s.DisplayName)
                                .ToList();
    // 启动异步轮询
    _pollingCts = new CancellationTokenSource();
    Task.Run(() => PollForNewStores(_pollingCts.Token), _pollingCts.Token);
}

private async Task PollForNewStores(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        await Task.Delay(5000, token); // 每5秒轮询一次
        try
        {
            this.Invoke(new Action(() => 
            {
                var currentStores = Application.Session.Stores.Cast<Outlook.Store>()
                                        .Select(s => s.DisplayName)
                                        .ToList();
                // 找出新增的存储名称
                var newStoreNames = currentStores.Except(_existingStoreNames).ToList();
                if (newStoreNames.Any())
                {
                    foreach (var name in newStoreNames)
                    {
                        var targetStore = Application.Session.Stores.Cast<Outlook.Store>()
                                            .FirstOrDefault(s => s.DisplayName == name);
                        if (targetStore != null)
                        {
                            // 执行新增存储的处理逻辑
                        }
                    }
                    // 更新现有列表
                    _existingStoreNames = currentStores;
                }
            }));
        }
        catch (Exception ex)
        {
            // 处理异常,如Outlook对象调用失败
        }
    }
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
    // 终止轮询任务
    _pollingCts?.Cancel();
    _pollingCts?.Dispose();
}

关键注意点

  • 所有Outlook对象模型的操作必须在UI线程执行,异步代码中需用this.Invoke切换线程。
  • 优先使用AccountAdded事件+类级Stores对象的组合方案,轮询仅作为兜底。

内容的提问来源于stack exchange,提问作者Willy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:10:12