从VisualStudio运行自定义的MSBuild目标

37

假设我向一个 csproj 文件添加了一个自定义目标,有没有办法从 Visual Studio 中运行该目标?我不想将其作为预构建或后构建步骤,我只想能够从 Visual Studio 运行此目标(及其依赖项)。

Suppose 我在一个 csproj 文件中添加了一个自定义目标。是否有一种方法可以从 Visual Studio 中运行该目标?我不想将其设置为预先构建或后构建步骤,我只想能够从 Visual Studio 运行此目标(以及它的依赖项)。
4个回答

42

有一种简单的方法(虽然不是完全令人满意),可以使用自定义外部工具。

假设您的项目文件进行了以下修改:

  <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 Add-in)。我不确定是否必须安装VS SDK才能获得此功能,它可以在扩展管理器中获得。
向导中选择以下选项: - Microsoft Visual Studio 2010 - 是的,创建“工具”菜单项 - 在应用程序启动时加载 - 我的Add-in永远不会出现模态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内部获取构建引擎实例,并让其在项目的另一个实例上执行构建。


8

如果您在Visual Studio内运行构建,则会有一个名为VisualStudioDir的构建变量。

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

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

如果要在Visual Studio之外的构建中执行,请按照以下步骤操作:

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

您需要以以下两种方式之一将自定义目标文件包含在其中。
  1. Set the environment variable CustomBeforeMicrosoftCommonTargets
  2. Edit you project file to include your custom targets file by adding an import

    <Imports Project="CustomBuildTasks.Targets"><Imports/>
    

5
你不必使用Exec进行编码,虽然这是一种方法。更简单的方法是按照以下步骤操作:
DefaultTargets="Build"属性更改为自定义目标,例如"All",如下所示:
DefaultTargets="All"

然后在您的自定义 "All" 目标中,您可以使用 DependsOnTargets 属性,如下所示:
"<Target Name="All" DependsOnTargets="ZipOutputFiles;Build">
  </Target>"

这将构建并在自定义"All"目标中输出zip文件。

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接