使用评估的 MSBuild 属性 值以编程方式强制更新 Visual Studio Intellisense

Programmatically force update Visual Studio Intellisense with evaluated MSBuild property value

我正在尝试创建一个 VSIX 扩展,它向 Visual Studio 工具栏添加一个下拉菜单以控制自定义 MSBuild 属性 的值。 该值确定项目中要包含的 COMReference 版本,并且必须在不覆盖 .csproj 文件的情况下进行设置。我的 .csproj 文件的一部分:

<Project ... >
<Choose>
    <When Condition="'$(MyProperty)'=='MyValue1'">
      <ItemGroup>
        <COMReference Include="ComLib">
          Version_1
        </COMReference>
      </ItemGroup>
    </When>
    <When Condition="'$(MyProperty)'=='MyValue2'">
      <ItemGroup>
        <COMReference Include="ComLib">
          Version_2
        </COMReference>
      </ItemGroup>
    </When>
  </Choose>
</Project>

我找到了 2 个可能的解决方案:

第一个

public static void SetGlobalBuildProperty( string property, string value )
{
    var projects = Microsoft.Build.Evaluation.ProjectCollection
                .GlobalProjectCollection
                .LoadedProjects;

    foreach ( Microsoft.Build.Evaluation.Project project in projects )
    {   
        project.SetGlobalProperty( property, value );
        project.MarkDirty();
        project.ReevaluateIfNecessary();    
    }
}

Broject 使用实际值正确构建,但 Intellisense 无法识别 COMReferences 中的任何内容 所以 Intellisense 功能不起作用,所有内容都带有红色下划线。

第二个:

将 属性 放到一个单独的文件中,并将其包含在主 csproj 中。通过 VSIX 修改 .props 文件后。

.csproj:

...
<Include Project="generated\MyProps.props"/>
<Coose> ... </Choose>
...

我的道具:

<Project ...>
  <PropertyGroup>
    <MyProperty Condition="'$(MyProperty )' == ''">MyValue1</MyProperty>
    <DefineConstants>$(DefineConstants);$(MyProperty)</DefineConstants>
  </PropertyGroup>
</Project>

这个解决方案非常有效。当我更改 MyValue1 时,仅在解决方案资源管理器中重新加载项目是不够的。有时甚至重启都不够Visual Studio,还需要删除.suo文件

我怎样才能让 Intellisense 更新有关项目的信息,或者也许有人知道这个问题的另一种解决方案?

我找到了解决方案。 此函数更新项目和 Intellisense:

 VSLangProj80.VSProject2.Refresh();

完整功能(刷新解决方案中的所有项目):

public static void SetGlobalBuildProperty( IServiceProvider package, string property, string value )
    {
        var projects = Microsoft.Build.Evaluation.ProjectCollection
            .GlobalProjectCollection
            .LoadedProjects;

        foreach ( var project in projects )
        {
            project.SetGlobalProperty( property, value );
            project.MarkDirty();
            project.ReevaluateIfNecessary();                    
        }
        var dte = package.GetService( typeof( DTE ) ) as DTE2;
        var solution = dte.Solution as Solution2;
        var dteProjects = GetSolutionProjects( solution ) //Get all solution projects.
        foreach( var project in dteProjects )
        {
            var vsProject = project.Object as VSProject2;
            vsproject.Refresh();
        }           
    }