使VisualStudio运行命令以生成C#代码

时间:2015-03-19 14:48:28

标签: c# visual-studio

我正在努力做一些非常简单的事情,但是尽管经过几个小时的互联网搜索并拼命输入我能找到的每个小例子片段,我确实不能让VS做我想做的事情。在这里真的很沮丧!

这就是我想要的:

  • 当我进行构建时,我希望VS找到项目中的每个*.fubar文件。
  • 对于每个*.fubar文件,我希望VS以输入文件作为参数执行fubar.exe
  • 我希望VS像往常一样编译生成的*.cs文件。

我该死的确信必须有可能实现这个简单的任务。我只需要弄清楚如何。


这就是问题所在。让我解释一下到目前为止我研究过的内容。

似乎你可以通过实现一些COM接口来编写VS扩展。但是这需要你编辑注册表来告诉VS插件的位置。显然这是完全不可接受的;我应该必须重新配置操作系统才能运行命令行工具!

似乎MSBuild应该是这种超可配置的构建管理工具,您可以在其中定义一组任意构建步骤及其相互依赖性。似乎应该在构建运行fubar.exe以生成源代码的构建C#编译步骤之前添加额外任务是微不足道的。然而,经过几个小时的尝试,我无法获得单个C#文件。

有些文档讨论了特殊的预构建和后构建步骤。但是,当构建步骤的数量和顺序被认为是任意的时候,需要一个特殊的钩子似乎很愚蠢。无论如何,我尝试了它,它仍然没有用。

要明确:使用项目文件使VS显示项目属性略有不同,并且不会使构建失败。但它也不会出现任何C#文件。 (至少,我无法在磁盘上的任何地方找到它们。我无法判断我的工具是否实际运行 - 我怀疑“不是”。)

可以任何人告诉我如何使这个微不足道的,微不足道的事情发挥作用? 必须成为一种方式!

2 个答案:

答案 0 :(得分:3)

我同意T4可能是一个更漂亮的解决方案,但下面的MsBuild代码可以工作。

您可以创建一个执行调用的自定义目标文件,我创建了一个只复制文件的文件,但该过程应该类似于调用您的可执行文件。

确保将FuBar文件设置为BuildAction" Fubars"。使用" AvailableItemName"在目标文件中定义了构建操作。属性。

您可能需要使用一些条件和存在检查来扩展以下脚本,以确保它在需要时运行。我将其称为convert.targets并将其放在项目目录中。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- Ensure Visual Studio puts the FuBars item in the Build Action dropdown -->
  <ItemGroup>
    <AvailableItemName Include="FuBars" />
  </ItemGroup>

  <!-- Execute action on all items matching FuBar (only if output is missing or input has changed) -->
  <Target Name="GenerateCodeFubar" Inputs="@(Fubars)" Outputs="$(MSBuildProjectDirectory)/obj/$(Configuration)/Fubars/%(Fubars.Identity).g.cs" >
    <MakeDir Directories="$(MSBuildProjectDirectory)/obj/$(Configuration)/Fubars/%(Fubars.RelativeDir)" />

    <Exec Command="cmd /c copy &quot;%(FuBars.FullPath)&quot; &quot;$(MSBuildProjectDirectory)/obj/$(Configuration)/Fubars/%(FuBars.Identity).g.cs&quot;"/>
  </Target>

  <!-- Pick up generated code in the Compile group. Separated from the execute action so that the previous action only runs when files have changes -->
  <Target Name="IncludeCodeFubarInCompile">
    <ItemGroup>
      <GeneratedFubars Include="$(MSBuildProjectDirectory)/obj/$(Configuration)/Fubars/%(FuBars.Identity).g.cs"/>
    </ItemGroup>

    <CreateItem Include="%(GeneratedFubars.FullPath)">
      <Output TaskParameter="Include" ItemName="Compile" />
    </CreateItem>
  </Target>

  <!-- Clean up for Rebuild or Clean -->
  <Target Name="DeleteCodeFubar">
   <RemoveDir Directories="$(MSBuildProjectDirectory)/obj/$(Configuration)/Fubars/" />
     <Delete Files="$(MSBuildProjectDirectory)/obj/$(Configuration)/fubars/**/*.g.cs" />
  </Target>

    <!-- Instruct MsBuild when to call target on Build-->
    <PropertyGroup>
        <BuildDependsOn>
            GenerateCodeFubar;
            IncludeCodeFubarInCompile;
            $(BuildDependsOn);
        </BuildDependsOn>
    </PropertyGroup>

    <!-- Instruct MsBuild when to call target on Clean-->    
    <PropertyGroup>
        <CleanDependsOn>
            DeleteCodeFubar;
            $(CleanDependsOn);
        </CleanDependsOn>
    </PropertyGroup>
</Project>

导入最后一个目标文件后,将其包含在.csproj中:

  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

  <!-- IMPORT HERE -->
  <Import Project="convert.targets" />
  <!-- END: IMPORT HERE -->

  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

您可能必须tell Visual Studio to turn off the Host Compiler,因为Visual Studio会缓存<Compile>组的内容以提高性能。虽然快速测试表明可能不需要这样做。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <!-- The first property group should not have any condition on it -->
  <PropertyGroup> 

    <!-- Include below item in the first PropertyGroup item:
    <UseHostCompilerIfAvailable>FALSE</UseHostCompilerIfAvailable>
  </PropertyGroup>

答案 1 :(得分:-1)

这非常容易。

在项目属性中,选择构建事件选项卡,然后输入正确的预构建事件命令行

在不知道footer.exe及其命令行args的情况下,我无法为您提供该应用程序的任何特定帮助。但是预构建事件对话框中有一个“宏”按钮,可以帮助您处理各种替换变量。


此外,VS附带了T4模板系统,它可能比footer.exe更合适。