以编程方式修改Visual Studio项目属性,而无需修改实际项目文件

时间:2019-07-19 15:48:04

标签: c# visual-studio msbuild envdte

我正在寻找一种方法,以防止Visual Studio将项目属性更改反映到* .csproj文件中。我只想为单个构建操作设置属性,然后应将其丢弃。

我在Visual Studio插件中使用EnvDTE自动化对象。以下是我的示例代码,该代码将"UseHostCompilerIfAvailable"属性设置(或更改)为"false",以用于将要构建的项目的特定配置和平台。构建是从Visual Studio UI启动的。

在构建初始化过程中的某个地方,Visual Studio会将所有项目属性更改都写入项目文件,这就是我要防止的事情。

dte.Events.BuildEvents.OnBuildProjConfigBegin += BuildEvents_OnBuildProjConfigBegin;
...
private void BuildEvents_OnBuildProjConfigBegin(string Project, string ProjectConfig, string Platform, string SolutionConfig)
{
    ThreadHelper.ThrowIfNotOnUIThread();
    IVsSolution solution = (IVsSolution)this.GetService(typeof(SVsSolution));
    solution.GetProjectOfUniqueName(Project, out IVsHierarchy hier);
    IVsBuildPropertyStorage storage = hier as IVsBuildPropertyStorage;
    storage.SetPropertyValue("UseHostCompilerIfAvailable", $"{ProjectConfig}|{Platform}", (uint)Microsoft.VisualStudio.Shell.Interop._PersistStorageType.PST_PROJECT_FILE, "false");
}

我知道我可以保存属性更改并在构建完成后还原它们,也可以缓存项目文件并最终将它们回滚,但是这些方法可能会产生不良影响。我什至很高兴得到一些想法,我应该朝哪个方向看。

3 个答案:

答案 0 :(得分:1)

为什么必须以编程方式进行操作?也许您可以尝试Directory.build.props文件。

将其放在解决方案文件夹中以自定义构建,而无需修改项目文件。

答案 1 :(得分:0)

从您的问题看来,您似乎必须处理VS默认插件SDK方法未涵盖的问题。

在这种情况下,您可以考虑尝试在VS中挂接NtCreateProcess,以获取需要创建的MSBuild时刻。

NtCreateProcess允许设置暂停标志。然后以暂停状态创建MSBuild。此刻,您可以对该过程进行更改。如果您有自定义加载器,请考虑在挂钩中使用它,而不是调用本机NtCreateProcess。

在注入的库内部做钩子以访问所需的属性。理想情况下,这些应该只是一些注册表项。但是,如果它在FS文件中的XML内,则它可能是用于访问XML属性的其他一些高级API。

您感兴趣的MSBuild进程内部的NtCreateProcess也需要以相同的方式进行挂钩,以将此逻辑传递给所有子进程,以使该解决方案更可靠。

答案 2 :(得分:0)

作为Directory.Build.props的替代方法,您是否考虑过将ImportBefore/ImportAfter目标文件拖放到MSBuildUserExtensionsPath指向的目录中?该目录中的所有文件将自动包含在构建中。

相关问题