从VisualStudio运行自定义的msbuild目标

Fra*_*man 34 msbuild visual-studio

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

Bri*_*ler 39

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

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

  <Target Name="CalledFromIde">
    <Error Text="Called from the IDE!" />
  </Target>
Run Code Online (Sandbox Code Playgroud)

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

  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
Run Code Online (Sandbox Code Playgroud)

运行它会产生输出:

  Build FAILED.

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

你正在做的是调用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;
}
Run Code Online (Sandbox Code Playgroud)

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

  <Target Name="CalledFromIde">
    <WriteLinesToFile File="CalledFromIde.txt" Lines="Called from the IDE!" />
  </Target>
Run Code Online (Sandbox Code Playgroud)

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

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


小智 5

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

将属性更改DefaultTargets="Build"为您创建的自定义目标,"All"如下所示:

DefaultTargets="All"
Run Code Online (Sandbox Code Playgroud)

然后,在自定义“All”目标中,您可以使用 DependsOnTargets 属性,如下所示:

"<Target Name="All" DependsOnTargets="ZipOutputFiles;Build">
  </Target>"
Run Code Online (Sandbox Code Playgroud)

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


Tim*_*ben 5

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

要仅执行VS构建会话,请执行以下操作:

<Target Name="Test" BeforeTargets="Build" Condition="'$(VisualStudioDir)' != ''>
</Target>
Run Code Online (Sandbox Code Playgroud)

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

<Target Name="Test" BeforeTargets="Build" Condition="'$(VisualStudioDir)' == ''>
</Target>
Run Code Online (Sandbox Code Playgroud)

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

  1. 设置环境变量CustomBeforeMicrosoftCommonTargets
  2. 通过添加导入来编辑项目文件以包含自定义目标文件

    <Imports Project="CustomBuildTasks.Targets"><Imports/>
    
    Run Code Online (Sandbox Code Playgroud)