c# - 如何从 VS 2017 的设置中获取当前的 Projects & Solutions 目录并使用 SDK 加载解决方案?
问题描述
我已经为 VS 2017 构建了一个自定义工具窗口扩展。除了两件事之外,一切正常:
我需要从工具/选项/项目和解决方案/位置中获取“项目位置”。
我还需要告诉当前的 VS 实例来加载解决方案或项目。
我已经在 VS SDK 上搜索了几天,并没有想出太多。我做到了这一点:
ShellSettingsManager sm = new ShellSettingsManager();
但这需要两个接口之一作为参数,IVsSettingsManager 或 IServiceProvider。
我实现了接口,当然,它创建了方法,所有这些方法都使用 NotImplemented 异常进行编码。
因此,由于我在这里完全一无所知,我希望有人能指出我正确的方向,如果不是直接告诉我如何去做。
解决方案
我终于想通了。您可以为 ShellSettingsManager 的构造函数提供一个 ServiceProvider。我看到的所有示例都刚刚使用:
SettingsManager sm = new ShellSettingsManager(ServiceProvider);
但是当我尝试这样做时,我得到“ServiceProvider 是一种类型,在给定的上下文中无效”
我终于找到了一个使用的例子:
SettingsManager sm = new ShellSettingsManager(ServiceProvider.GlobalProvider);
然后同样的例子继续......
SettingsStore ss = sm.GetReadOnlySettingsStore(SettingsScope.UserSettings);
这是我必须自己解决剩下的问题的地方。
SettingsStore 中有两个枚举,GetPropertyNames 和 GetSubCollectionNames。这些有助于找到我需要的收藏品和财产。所以首先我这样做了:
string msg = "";
foreach (string s in ss.GetPropertyNames(""))
{
msg += s + "\r\n";
}
MessageBox.Show(msg);
作为参数的空字符串获取根集合属性,这就是我需要的。
所以现在我终于检索到了我需要的值。
string DefaultNewProjectLocation = Environment.ExpandEnvironmentVariables(ss.GetString("", "DefaultNewProjectLocation"));
第一个参数,空字符串,是根集合,第二个参数是我想要的属性。它返回:
%USERPROFILE%\source\repos
扩展环境变量给了我文字路径。
现在开始弄清楚如何让当前的 VS 实例加载在我的工具窗口中选择的项目。
编辑:经过一整天的搜索,终于让 Visual Studio 在我的扩展正在运行的实例中加载一个项目。有几个人告诉我使用 Process.Start 并将路径传递给解决方案文件,但这会启动另一个 Visual Studio 实例并将其加载到那里。
我找到了 DTE.ExecuteCommand(string Command, string Args) 但不知道这是否是我需要的。然后我读到一些说它执行工具/选项/环境/键盘部分中可用的命令的东西。我在那里仔细阅读并找到了“File.OpenProject”,并认为我可以将解决方案文件作为参数发送。但是在这个过程中还有一个问题......
添加对 EnvDTE 的引用并尝试以下操作:
DTE.ExecuteCommand("File.OpenProject", "\"" + PathToSlnFile + "\"");
只是给了我一个错误说,
非静态字段、方法或属性“_DTE.ExecuteCommand(string, string)”需要对象引用
我尝试实例化它
var dte = new DTE();
但这只是给了我一些关于无法读取有关 COM 库的内容的运行时错误。我发现了一百万个使用 DTE.ExecuteCommand 的示例,但没有一个示例显示如何获取对它的引用。我确实在 Google 图书“掌握 Visual Studio .NET:充分利用 Visual Studio .NET 环境”中找到了这一点
获取对 DTE 对象的引用的方式取决于您编写的代码类型。宏只使用由宏环境提供的称为 DTE 的全局变量。当 VS.NET 初始化它们时,加载项会传递对此对象的引用。
好吧,这仍然没有告诉我任何事情。我如何获得该参考?!?
然后我很幸运。我终于偶然发现了一个随机页面(我会链接它,但我已经关闭它并且认为我再也找不到它了)。它给了我我需要的东西。
private DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
而现在,我可以做到这一点,而且效果很好!
dte.ExecuteCommand("File.OpenProject", "\"" + PathToSolutionFile + "\"");
希望这将使像我这样的其他可怜的懒惰者免于花费整整三天的时间搜索并在他们尝试编写 Visual Studio 扩展时一无所获。
推荐阅读
- mysql - 将一个表的记录分布到具有相似表结构的多个表中是否是个好主意
- html - Vue.js 离开动画没有按预期工作
- jquery - 无法调用 Web 方法
- reactjs - 对孩子使用“React.ReactNode”类型时出错。我应该使用哪种类型?
- azure - 使用 Ansible 自动化 Azure 逻辑应用
- java - 多个数据源的 Spring Boot 测试配置
- javascript - Highchart 在初始加载时不显示正确的大小,仅在 React js 中调整窗口大小时调整大小
- java - 由于 ClassNotFoundException 错误而无法运行应用程序
- node.js - 用于 SPFX 共享点 webpart 的节点 JS 和 npm 安装
- python - 如何组织 python 代码以便顺利工作并轻松分发?