指定生成事件 (C#)
使用生成事件指定在生成开始之前或生成完成后运行的命令。
指定生成事件
在 解决方案资源管理器中,选择要为其指定生成事件的项目。
在“项目”菜单上,单击“属性”。
选择“生成事件”选项卡。
在 预生成事件命令行 框中,指定生成事件的语法。
注释
如果项目是最新的且没有触发构建,则预构建事件不会运行。
在 生成后事件命令行 框中,指定生成事件的语法。
注释
在运行 .bat 文件的所有生成后命令之前添加
call
语句。 例如call MyFile.bat
或call MyFile.bat call MyFile2.bat
。 路径可以是输出文件夹的绝对路径,也可以是其相对路径。在 运行生成后事件 框中,指定生成后事件应在何种条件下运行。
注释
若要添加冗长的语法,或从 预生成事件/生成后事件命令行对话框中选择任何生成宏,请单击省略号按钮(...)以显示编辑框。
在 解决方案资源管理器中,选择要为其指定生成事件的项目。
在“项目”菜单上,单击 {ProjectName} 属性(或在 解决方案资源管理器中,按 Alt+Enter)。
选择“生成”>“事件”。
在 预生成事件 部分中,指定生成事件的语法。
注释
如果项目是最新的且没有触发构建,则预生成事件不会运行。
在 生成后事件 部分中,指定生成事件的语法。
注释
在运行 .bat 文件的所有生成后命令之前添加
call
语句。 例如call MyFile.bat
或call MyFile.bat call MyFile2.bat
。 路径可以是项目文件夹的绝对路径,也可以是其相对路径。在 何时运行生成后事件 部分中,指定何种条件下需运行生成后事件。
创建构建事件命令
生成事件命令可以包含任何在命令提示符或 .bat 文件中有效的命令。 Windows 命令参考中记录了可用命令。 批处理文件的名称应先于 call
,以确保执行所有后续命令。 批处理文件本身从输出文件夹运行,例如,bin/Debug
。 如果您在所有配置中需要相同的批处理文件,可以将它放在与项目文件相同的文件夹中,然后使用相对路径,例如:call ../../prebuild.bat
。
可以通过输入 PowerShell MyPowerShellScript.ps1
等命令来执行 PowerShell 脚本。 PowerShell 脚本的路径可能是绝对路径,也可能是相对于项目目录的路径。 需要确保在操作系统上为 PowerShell 脚本设置适当的执行策略,以便运行脚本。 请参阅关于执行策略。
如果要使用另一个 shell(如 bash),通常使用与从 Windows 命令提示符启动 shell 脚本相同的命令语法。 使用第三方 shell 超出了本文档的范围,但 Stack Overflow 等站点可能很有帮助。
在项目文件中
执行前面的步骤时,Visual Studio 会通过添加 PreBuild
或 PostBuild
目标以及执行所提供的步骤所需的 MSBuild 代码来修改项目文件。 可以打开项目文件并查看步骤。 修改项目文件中的步骤是可以的。 保存更改后,你将在项目属性的 生成 > 事件 部分中看到更改。
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="call prebuild.bat" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="call postbuild.bat" />
</Target>
Exec
元素引用 MSBuild Exec
任务。 有关可用于自定义执行的其他参数的信息,请参阅 Exec 任务。 例如,可以使用 WorkingDirectory
设置运行可执行文件的文件夹。 默认值为包含项目文件的目录。
<Exec Command="call prebuild.bat" WorkingDirectory="$(OutDir)">
可以使用 MSBuild 属性(宏),例如上一示例中的 OutDir
,正如本文后面 宏部分中所讨论的那样。
错误和其他输出
生成事件的输出将写入“输出窗口”的“生成”部分。 若要打开它,请选择 视图>其他窗口、输出窗口,或按 Ctrl+Alt+O。 在“显示输出来源”旁边的下拉列表中,选择“生成”。
如果预生成事件或生成后事件未成功完成,可通过使用除零 (0) 之外的代码退出事件操作来终止生成。 零退出代码指示作成功;任何其他退出代码都被视为错误。
如果预生成事件失败,可能会在 错误列表 窗口中看到如下所示的错误:
MSB3073 The command "call c:\source\repos\prebuild.bat" exited with code 1.
如果 错误列表 窗口中没有足够的信息,则可以尝试使用 输出窗口 查看完整的生成输出,包括批处理文件的任何输出。
小贴士
“错误列表”窗口只限于一行输出,即你为事件输入的第一行。 如果“错误列表”窗口输出对你很重要,请避免在事件中放置多行。 在 Windows 命令提示符或操作系统中创建批处理文件,然后使用 call mybatchfile.bat
进行事件处理。 在批处理文件本身中包含命令。
有关可在批处理文件中使用的命令的指南,请参阅 Windows 命令。
宏
常见的“宏”(实际为 MSBuild 属性)列在 MSBuild 通用属性。 对于 .NET SDK 项目(.NET Core 或 .NET 5 及更高版本),MSBuild 属性中列出了 Microsoft.NET.Sdk的其他属性。
在生成事件的脚本中,你可能想要引用某些项目级变量的值,例如项目的名称或输出文件夹的位置。 在早期版本的 Visual Studio 中,这些宏称为 宏。 在最新版本的 Visual Studio 中,等同于宏的是 MSBuild 属性。 MSBuild 是 Visual Studio 在执行生成时用于处理项目文件的生成引擎。 IDE 中的生成事件会在项目文件中产生一个 MSBuild 目标。 可以使用项目文件中目标中可用的任何 MSBuild 属性(例如,$(OutDir)
或 $(Configuration)
)。 在这些事件中可用的 MSBuild 属性取决于在项目文件中隐式或显式导入的文件,例如 .props
和 .targets
文件,以及项目文件中设置的属性,例如在 PropertyGroup
元素中设置。 请小心使用每个属性的准确拼写。 如果错报属性,则不会报告错误;相反,未定义属性的计算结果为空字符串。
例如,假设指定了预生成事件,如下所示:
该预构建事件会导致在你的项目文件中出现以下条目,称为 Target
:
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="echo Configuration: $(Configuration)
echo DevEnvDir: $(DevEnvDir)
echo OutDir: $(OutDir)
echo ProjectDir: $(ProjectDir)
echo VisualStudioVersion: $(VisualStudioVersion)
echo AssemblySearchPaths: $(AssemblySearchPaths)
echo AssemblyName: $(AssemblyName)
echo BaseIntermediateOutputPath: $(BaseIntermediateOutputPath)
echo CscToolPath: $(CscToolPath)" />
</Target>
生成事件作为一个目标出现,其中包含 Exec 任务和你指定为 Command
的输入。 换行符使用 XML 进行编码。
在此示例中生成项目时,预生成事件会输出某些属性的值。 在此示例中,$(CscToolPath)
不生成任何输出,因为它未定义。 它是一个可选属性,你可以在项目文件中定义,以提供 C# 编译器的自定义实例的路径(例如,如果测试了不同版本的 csc.exe或实验性编译器)。
生成事件的输出将写入生成输出,你可在“输出”窗口中找到该输出。 在“显示来自 的输出”下拉列表中,选择“生成”。
Build started...
1>------ Build started: Project: ConsoleApp4, Configuration: Debug Any CPU ------
1>You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
1>Configuration: Debug
1>DevEnvDir: C:\Program Files\Microsoft Visual Studio\2022\Preview\Common7\IDE\
1>OutDir: bin\Debug\net6.0\
1>ProjectDir: C:\source\repos\ConsoleApp4\ConsoleApp4\
1>VisualStudioVersion: 17.0
1>ALToolsPath:
1>AssemblySearchPaths: {CandidateAssemblyFiles};{HintPathFromItem};{TargetFrameworkDirectory};{RawFileName}
1>AssemblyName: ConsoleApp4
1>BaseIntermediateOutputPath: obj\
1>CscToolsPath:
1>Skipping analyzers to speed up the build. You can execute 'Build' or 'Rebuild' command to run analyzers.
1>ConsoleApp4 -> C:\source\repos\ConsoleApp4\ConsoleApp4\bin\Debug\net6.0\ConsoleApp4.dll
注释
某些场景需要比生成事件更复杂的构建操作。 例如,对于许多常见的代码生成方案,需要处理清理和重建操作,并且您可能希望为代码生成步骤启用增量构建,以便仅当输出与输入相比已过时时,才运行该步骤。 MSBuild 旨在智能处理所有这些方案。 考虑创建一个自定义目标,用于指定 AfterTargets
或 BeforeTargets
在生成过程中的特定点运行;为了在高级场景中进一步控制,可以考虑创建自定义任务,或查看可自定义生成的不同方式。
示例
在项目文件夹中创建名为
postbuild.bat
的批处理文件,内容如下:echo Copying output file %1 to %1.copy copy %1 %1.copy
回想一下,在批处理文件中,
%1
引用传入的第一个参数。在项目属性的 生成后事件 部分中调用批处理文件,并使用 MSBuild 属性
$(TargetPath)
传递参数。call postbuild.bat $(TargetPath)
生成项目并检查输出文件夹。 生成的程序集旁边应会显示复制的文件。 在“输出窗口”的“生成”部分中,应会看到批处理文件输出:
1>Output file is C:\source\repos\ConsoleApp-BuildEvents\ConsoleApp-BuildEvents\bin\Debug\net6.0\ConsoleApp-BuildEvents.dll 1> 1 file(s) copied. ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== ========== Build started at 12:00 PM and took 00.723 seconds ==========