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

如何检测待保存文件?调用Dte.Documents遇HRESULT:0x8000000A异常

解决检测待保存文件时的HRESULT: 0x8000000A异常问题

我尝试参考方案检测处于“待保存状态”的文件,编写了如下代码,但运行时抛出异常The data necessary to complete this operation is not yet available. (Exception from HRESULT: 0x8000000A),请问遗漏了什么?

编写的辅助类代码

using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;

namespace Link
{
    public static class ProjectHelpers
    {
        static ProjectHelpers()
        {
            // Rely on caller being on UI thread as shouldn't do it here in the constructor.
#pragma warning disable VSTHRD010 // Invoke single-threaded types on Main thread
            Dte = (DTE)Package.GetGlobalService(typeof(DTE));
#pragma warning restore VSTHRD010 // Invoke single-threaded types on Main thread
            Dte2 = (DTE2)Package.GetGlobalService(typeof(DTE));
        }

        public static DTE Dte { get; }

        public static DTE2 Dte2 { get; }
    }
}

调用代码

try
{
      await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

      // Enumerate through open documents
      foreach (Document doc in ProjectHelpers.Dte.Documents)
      {
         // Check if the document has unsaved changes
         if (!doc.Saved)
         {
            Console.WriteLine($"Unsaved changes in document: {doc.FullName}");
         }
      }
}
catch (Exception ex)
{
      Console.WriteLine(ex.Message);
}

问题原因与解决方法

问题根源

这个异常(HRESULT: 0x8000000A,即E_PENDING)是因为静态构造函数执行时机过早,此时Visual Studio的DTE服务还未完全初始化,获取到的DTE实例处于未就绪状态,访问其Documents集合时就会抛出该异常。

修复方案

1. 修改辅助类,延迟获取DTE实例

将静态构造函数中直接获取DTE的逻辑,改为在属性 getter 中延迟获取,并确保处于UI线程:

using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;

namespace Link
{
    public static class ProjectHelpers
    {
        private static DTE _dte;
        private static DTE2 _dte2;

        public static DTE Dte
        {
            get
            {
                ThreadHelper.ThrowIfNotOnUIThread();
                return _dte ??= (DTE)Package.GetGlobalService(typeof(DTE));
            }
        }

        public static DTE2 Dte2
        {
            get
            {
                ThreadHelper.ThrowIfNotOnUIThread();
                return _dte2 ??= (DTE2)Package.GetGlobalService(typeof(DTE));
            }
        }
    }
}

2. 增强调用代码的健壮性

在调用时增加DTE实例有效性检查,并针对E_PENDING异常做特殊处理:

try
{
    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

    var dte = ProjectHelpers.Dte;
    if (dte == null)
    {
        Console.WriteLine("DTE服务不可用");
        return;
    }

    // 枚举打开的文档
    foreach (Document doc in dte.Documents)
    {
        if (!doc.Saved)
        {
            Console.WriteLine($"存在未保存更改的文档: {doc.FullName}");
        }
    }
}
catch (Exception ex) when (ex.HResult == -2147483638) // 对应0x8000000A
{
    Console.WriteLine("DTE服务尚未就绪,请稍后重试");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

说明

延迟获取DTE实例能确保在真正需要使用服务时,VS已经完成了相关初始化;同时在属性 getter 中强制检查UI线程,符合VS扩展开发的线程安全要求。针对E_PENDING的异常捕获,能进一步提升代码在VS启动阶段的健壮性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:55:37