如何从 VS 2017 中的设置获取当前项目和解决方案目录并使用 SDK 加载解决方案?

How can I get the current Projects & Solutions directory from the settings in VS 2017 and load solution using SDK?

我已经为 VS 2017 构建了一个自定义工具 window 扩展。除两点外一切正常:

我需要从 Tools/Options/Projects 和 Solutions/Locations 获取 "Projects location"。

我还需要告诉 VS 的当前实例加载解决方案或项目。

我已经在 VS SDK 上搜索了好几天,但没能找到太多。我做到了这一点:

ShellSettingsManager sm = new ShellSettingsManager();

但这需要两个接口之一作为参数,IVsSettingsManager 或 IServiceProvider。

我实现了接口,当然,它创建了方法,所有代码都使用 NotImplemented 异常进行编码。

既然我在这里完全一无所知,我希望有人能给我指出正确的方向,如果不是直接告诉我怎么做的话。

我终于明白了。您可以为 ShellSettingsManager 的构造函数提供一个 ServiceProvider。我看到的所有示例都使用了:

SettingsManager sm = new ShellSettingsManager(ServiceProvider);

但是当我尝试这样做时,我得到了 "ServiceProvider is a type, which is not valid in the given context"

我终于找到了一个使用的例子:

SettingsManager sm = new ShellSettingsManager(ServiceProvider.GlobalProvider);

同样的例子继续......

SettingsStore ss = sm.GetReadOnlySettingsStore(SettingsScope.UserSettings);

这是我必须自己解决其余问题的地方。

SettingsStore 中有两个枚举,GetPropertyNames 和 GetSubCollectionNames。这些有助于找到我需要的 collection 和 属性。所以首先我这样做了:

        string msg = "";
        foreach (string s in ss.GetPropertyNames(""))
        {
            msg += s + "\r\n";
        }
        MessageBox.Show(msg);

作为参数的空字符串获取根 collection 属性,这就是我需要的。

所以现在我终于检索到了我需要的值。

string DefaultNewProjectLocation = Environment.ExpandEnvironmentVariables(ss.GetString("", "DefaultNewProjectLocation"));

第一个参数,空串,就是根collection,第2个参数,就是我要的属性。它返回:

%USERPROFILE%\source\repos

扩展环境变量给我文字路径。

现在了解如何获取 VS 的当前实例以加载在我的工具中选择的项目 window。

编辑:经过又一整天的搜索,终于 Visual Studio 在我的扩展名为 运行 的实例中加载一个项目。几个人告诉我使用 Process.Start 并将路径传递到解决方案文件,但这启动了 Visual Studio 的另一个实例并将其加载到那里。

我找到了 DTE.ExecuteCommand(string Command, string Args) 但不知道那是否是我需要的。然后我读到一些东西说它执行 Tools/Options/Environment/Keyboard 部分中可用的命令。我在那里仔细阅读并找到 "File.OpenProject" 并认为我可以将解决方案文件作为参数发送。但是还有一个问题...

添加对 EnvDTE 的引用并尝试这样做:

DTE.ExecuteCommand("File.OpenProject", "\"" + PathToSlnFile + "\"");

刚刚给我一个错误,说

an object reference is required for the non-static field, method or Property '_DTE.ExecuteCommand(string, string)'

我试过实例化它

var dte = new DTE();

但这只是给了我一些关于无法读取有关 COM 库的信息的运行时错误。我发现了一百万个使用 DTE.ExecuteCommand 的例子,但没有一个展示了如何获得对它的引用。我确实在 Google 书中找到了这个,"Mastering Visual Studio .NET: Getting the Most Out of the Visual Studio .NET Environment"

The way in which you obtain a reference to the DTE object will depend on what type of code you are writing. Macros just use a global variable provided by the macro environment called DTE. Add-ins are passed a reference to this object when VS.NET initializes them.

好的,这仍然没有告诉我任何信息。我如何获得该参考资料?!?

然后我很幸运。我终于偶然发现了一个随机页面(我想 link 但我已经将其关闭并且认为我再也找不到它了)。它给了我我需要的东西。

private DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;

现在,我可以做到这一点,而且效果很好!

dte.ExecuteCommand("File.OpenProject", "\"" + PathToSolutionFile + "\""); 

希望这可以避免像我这样的其他可怜的懒汉花费整整三天的时间搜索并在他们尝试编写 Visual Studio 扩展时一无所获。