通过Visual Studio自动化设置项目的OutputPath属性

Doo*_*ins 10 c# msbuild envdte visual-studio-2012

我正在写一个VSIX包允许用户批量修改当前加载的解决方案的项目,所有的主动配置的OutputPath属性(见令人难以置信的恼人的步骤#4 在这里).

我遇到了一个非常具体的问题:当将属性设置为包含宏"$(SolutionDir)\bin\Debug"的值时(例如,写入.csproj的值被转义如下:

<OutputPath>%24%28SolutionDir%29\bin\Debug\</OutputPath>
Run Code Online (Sandbox Code Playgroud)

而不是让MSBuild扩展宏,而是创建一个名为的实际物理文件夹$(SolutionDir).我想以某种方式绕过这种逃避.

毫无疑问,MSDN文档在该领域缺乏.

我的初始代码如下:

private void MenuItemCallback(object sender, EventArgs e)
{
    SolutionWideOutputDialogWindow dialog = new SolutionWideOutputDialogWindow();
    dialog.ShowModal();
    if (!dialog.DialogResult.HasValue || !dialog.DialogResult.Value)
    {
        return;
    }

    string requestedOutputPath = dialog.outputPathTextBox.Text;
    Solution2 solution = _dte2.Solution as Solution2;
    if (solution == null)
    {
        return;
    }

    Projects projects = solution.Projects;
    foreach (Project project in projects)
    {
        Property outputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath");
        outputPath.Value = requestedOutputPath;
        project.Save();
    }
}
Run Code Online (Sandbox Code Playgroud)

非常感谢任何人的帮助.

dej*_*now 14

遗憾的是,从项目属性进行编辑时,Visual Studio将转义特殊字符.

要解决此问题,请直接在文本编辑器中编辑.csproj文件.

例如,更改:

<OutputPath>%24%28SolutionDir%29\bin\Debug\</OutputPath>
Run Code Online (Sandbox Code Playgroud)

至:

<OutputPath>$(SolutionDir)\bin\Debug\</OutputPath>
Run Code Online (Sandbox Code Playgroud)

  • **建议**:如果使用文本编辑器设置将`<OutputPath>`设置为`$(SolutionDir)\ bin\Debug`它将显示为`..\..\..\_bin\Debug `in*Visual Studio 2013*.好消息是,宏观将保持不变.正如所料,如果对*Visual Studio*中的`Output Path:`进行任何更改,那么宏将被删除.仅供参考 - *Microsoft*使用本网站帮助确定功能请求的优先级:[UserVoice.com](https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3089044-would-be-very-helpful- IF-C-扩宏使用的-i)的 (3认同)

Doo*_*ins 9

这是我最终做的事情:

我试图解决的问题不是重复我自己(DRY)并指定一个解决方案范围的输出目录(在一个包含很多项目的解决方案中) - 也就是说,在编译解决方案时,所有项目的输出目录都设置为像$(SolutionDir)bin\Debug$(SolutionDir)bin\Release.值得一提的是,一些项目包含在存储库和多个解决方案中.

起初,我创建了一个MSBuild文件(一个<Project>XML - 称之为MySolution.sln.targets).在其中,我定义了一个<PropertyGroup><OutputPath>属性覆盖为:

$(SolutionDir)bin\$(Platform)\$(Configuration)
Run Code Online (Sandbox Code Playgroud)

然后,在构建目标导入之前,我将以下导入添加到所有相关项目:

<Import Project="$(SolutionPath).targets" />
Run Code Online (Sandbox Code Playgroud)

这样,每个解决方案都有一个附带的.targets文件来定义我想要解决方案范围的东西.

这很好用,但后来遇到了以下问题:上面提到的$(Platform)$(Configuration)宏指的是项目的属性,而不是解决方案属性.如果我的解决方案的Debug/Any CPU配置仍然在其Release配置中构建了一些非常具体的项目,会发生什么?据我所知,在彻底检查了文档后,没有导出具有解决方案范围粒度的宏.

我找到了ceztko的Visual Studio扩展,它使Visual Studio完全导出了我正在寻找的宏 - 但经过一些实验和摆弄后,我发现这个扩展设置得太晚了 - 只有在构建解决方案时.这导致Visual Studio的增量构建功能出现问题 - 它一直认为项目已经过时了,因为它看错了地方 - 它不知道变量,但MSBuild.exe是.

我开始摆弄IVsUpdateSolutionEvents 界面,在调用每个方法时跟踪 - 然后发现IVsUpdateSolutionEvents.OnActiveProjectCfgChange在新的Visual Studio中打开1项目解决方案时,或者在将解决方案的配置从Debug更改为Release时调用两次.进一步的摆弄显示,如果我在两种解决方案配置中将项目设置为在Release中编译,则此方法现在在更改解决方案配置时被调用一次而不是两次.

我将扩展的存储库分叉并通过将宏设置逻辑移动到上述方法来修改问题.你可以在这里找到它.

免责声明:这可能与IDE的批量生成操作无法很好地交互,并且需要您在从MSBuild.exe的命令行构建时自行导出这些属性.

祝你的旅行顺利.