从VisualStudio运行自定义的msbuild目标

时间:2011-02-26 02:49:08

标签: visual-studio msbuild

假设我将自定义目标添加到csproj文件中。有没有办法从visual studio运行该目标?我不希望它成为预建或后构建步骤,我只是希望能够从visual studio运行这个目标(及其依赖项)。

4 个答案:

答案 0 :(得分:39)

使用自定义外部工具有一种简单的方法(尽管不是很令人满意)。

假设您的项目文件有以下修改:

  <Target Name="CalledFromIde">
    <Error Text="Called from the IDE!" />
  </Target>

转到工具|外部工具并添加如下:

  Title:      Called from IDE
  Command:    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe
  Arguments:  $(ProjectDir)$(ProjectFileName) /t:CalledFromIde
  Initial directory:  $(ProjectDir)
  Use Output window:  checked

运行它会产生输出:

  Build FAILED.

  "F:\Code\CsProject\CsProject.csproj" (CalledFromIde target) (1) ->
  (CalledFromIde target) -> 
    F:\Code\CsProject\CsProject.csproj(57,5): error : Called from the IDE!

您正在做的是将MSBuild称为外部工具并让它直接运行目标。您必须提供MSBuild的完整路径,因为IDE不会保留与其创建的构建环境相同的属性。

您可以通过确定设置Tools.ExternalCommand#中的#命令来将其挂钩到快捷方式。

如果您正在寻找更复杂的解决方案,那么它会更复杂一些。简而言之(对于VS2010):

1)创建VS Addin(文件|新建|项目|其他项目类型|可扩展性| Visual Studio加载项)。我不确定您是否必须安装VS SDK才能获得此功能,它可以在扩展管理器中使用。

在向导中选择以下选项:   - Microsoft Visual Studio 2010   - 是的,创建一个“工具”菜单项   - 应用程序启动时加载   - 我的加载项永远不会提供模态UI,并且可以与命令行构建一起使用。

2)添加对Microsoft.Build和Microsoft.Build.Framework

的引用

3)在Connect.cs文件中找到Exec的实现

4)用以下代码替换它:

public void Exec(
    string commandName,
    vsCommandExecOption executeOption,
    ref object varIn,
    ref object varOut,
    ref bool handled)
{
    handled = false;
    if (executeOption != vsCommandExecOption.vsCommandExecOptionDoDefault)
        return;
    if (commandName != "BuildAddin.Connect.BuildAddin")
        return;

    var doc = _applicationObject.ActiveDocument;
    var projectItem = doc.ProjectItem;
    var project = projectItem.ContainingProject;
    var evalProject =
        Microsoft.Build.Evaluation.ProjectCollection
        .GlobalProjectCollection.LoadProject(project.FullName);
    var execProject = evalProject.CreateProjectInstance();

    bool success = execProject.Build("CalledFromIde", null);

    var window = _applicationObject.Windows.Item(Constants.vsWindowKindOutput);
    var output = (OutputWindow)window.Object;
    OutputWindowPane pane = output.OutputWindowPanes.Add("BuildAddin");
    pane.OutputString(success ? "built /t:CalledFromIde" : "build failed");

    handled = true;
    return;
}

5)调试时更好的自定义目标,因为上一个错误:

  <Target Name="CalledFromIde">
    <WriteLinesToFile File="CalledFromIde.txt" Lines="Called from the IDE!" />
  </Target>

6)上面的代码没有错误检查以简洁,你会希望更清洁,因为它将在IDE中运行。插件将在“工具”菜单上放置一个菜单项。如上所述,它只是查找包含当前活动编辑器文档的项目,无论您正在烹饪什么,都需要更好的管道。

此技术从IDE中获取构建引擎实例,并使其在项目的单独实例上执行构建。

答案 1 :(得分:5)

如果您在Visual Studio中运行构建,则在构建期间将有一个VisualStudioDir的构建变量。

仅执行VS构建会话执行此操作:

<Target Name="Test" BeforeTargets="Build" Condition="'$(VisualStudioDir)' != ''>
</Target>

要仅在VS之外的构建中执行,请执行以下操作:

<Target Name="Test" BeforeTargets="Build" Condition="'$(VisualStudioDir)' == ''>
</Target>

您需要以两种方式之一包含自定义目标文件。

  1. 设置环境变量CustomBeforeMicrosoftCommonTargets
  2. 通过添加导入

    编辑项目文件以包含自定义目标文件
    <Imports Project="CustomBuildTasks.Targets"><Imports/>
    

答案 2 :(得分:3)

您不必使用Exec进行编码,尽管这是一种方法。更简单的方法是执行以下操作:

DefaultTargets="Build"属性更改为您创建的自定义目标,比如说"All"

DefaultTargets="All"

然后在您的自定义&#34; All&#34; target,您可以使用DependsOnTargets属性,如下所示:

"<Target Name="All" DependsOnTargets="ZipOutputFiles;Build">
  </Target>"

然后,这将构建并输出zip文件到您的自定义"All"目标中。

答案 3 :(得分:0)

前段时间,我遇到了同样的问题,因此决定编写VS加载项。 试试吧:

MsBuildTaskExplorer

https://github.com/Serg046/MsBuildTaskExplorer

https://marketplace.visualstudio.com/items?itemName=saaseev.MsBuildTaskExplorer