Visual Studio扩展中如何不打开文件获取文件内容?
嘿,这个问题我做VS扩展的时候也踩过坑!你现在用TextDocument的方式确实会强制打开未加载的文档,没做空判断的话还容易崩。下面给你两个靠谱的解决方向,优先推荐第一种,简单直接还省心:
方法一:获取项目项物理路径,用System.IO直接读取
这是最通用的方案,完全绕开VS的文档对象,直接操作文件系统。你可以通过ProjectItem的FileNames属性拿到文件的完整物理路径,然后用.NET的IO类读取内容:
// 获取项目项对应的物理文件路径(索引1对应磁盘上的完整路径) string filePath = projectItem.FileNames[1]; // 可选:先检查文件是否存在,避免异常 if (System.IO.File.Exists(filePath)) { // 直接读取文件内容,无需打开VS文档 string text = System.IO.File.ReadAllText(filePath); // 这里处理你的文本逻辑即可 }
为什么这个方法可行?
VS里的ProjectItem.FileNames[1]会直接返回文件在磁盘上的完整路径,不管文件有没有在VS中打开。这样你就不用依赖Document对象,自然不会触发强制打开文件的行为,也彻底避免了空引用崩溃的问题。如果文件有特殊编码,还可以在ReadAllText里指定编码,比如System.IO.File.ReadAllText(filePath, Encoding.GetEncoding("GB2312"))。
方法二:用VS API无加载读取(进阶场景)
如果碰到虚拟项目项(没有对应物理文件)这类特殊场景,不能用System.IO,可以尝试VS的IVsPersistentTextImage接口读取内容,不过这个方法相对复杂:
// 获取项目的IVsHierarchy接口 IVsHierarchy hierarchy = (IVsHierarchy)projectItem.ContainingProject.Object; uint itemId = (uint)projectItem.ID; // 获取IVsPersistentTextImage服务 if (hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_PersistentTextImage, out object textImageObj) == Microsoft.VisualStudio.VSConstants.S_OK) { IVsPersistentTextImage textImage = (IVsPersistentTextImage)textImageObj; textImage.GetText(0, -1, out string text); // 处理读取到的文本内容 }
这个方法只适用于支持持久化文本的项目项,普通文件项目项还是第一种方法更简单实用。
关于你原有代码的问题
你原来的代码崩溃,是因为当文件未打开时projectItem.Document会返回null,直接访问Object("TextDocument")就会抛出NullReferenceException。就算加了空判断,还是会触发VS打开文件的行为,不符合你“无需打开文件”的需求。
内容的提问来源于stack exchange,提问作者Paul Michaels

