如何检测待保存文件?调用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
相关产品推荐
相关产品推荐

