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

时间:2013-11-29 14:42:48

标签: c# visual-studio-2012 msbuild envdte

我正在编写一个VSIX包,允许用户批量编辑当前加载的解决方案中项目的所有活动配置的OutputPath属性(请参阅令人难以置信的烦恼步骤#4 here)。

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

<OutputPath>%24%28SolutionDir%29\bin\Debug\</OutputPath>

而不是让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();
    }
}

非常感谢任何人的帮助。

2 个答案:

答案 0 :(得分:12)

从项目属性进行编辑时,不幸的是,Visual Studio将转义特殊字符。

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

例如,更改:

<OutputPath>%24%28SolutionDir%29\bin\Debug\</OutputPath>

为:

<OutputPath>$(SolutionDir)\bin\Debug\</OutputPath>

答案 1 :(得分:9)

这是我最终做的事情:

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

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

$(SolutionDir)bin\$(Platform)\$(Configuration)

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

<Import Project="$(SolutionPath).targets" />

这样,每个解决方案都有一个附带的.targets文件,用于定义我希望在解决方案范围内的所有内容。

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

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

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

我分叉了扩展程序的存储库并通过将宏设置逻辑移动到上述方法来修正了问题。你可以找到它here

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

祝你旅途中好运。