指定建置事件 (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 指令碼的執行原則已適當設定,才能執行指令碼。 請參閱關於執行原則。
如果您想要使用另一個殼層,例如 bash,您通常會使用與從 Windows 命令提示字元啟動殼層指令碼相同的命令語法。 使用第三方殼層超出本文件的範圍,但是 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
工作。 如需可用來自訂執行之其他參數的資訊,請參閱執行工作。 例如,您可以使用 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 和更新版本),其他屬性會列在適用於 Microsoft.NET.Sdk 的 MSBuild 屬性。
在建置事件的指令碼中,您可能想要參考某些專案層級變數的值,例如專案的名稱或輸出資料夾的位置。 在舊版 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 ==========