.NET 專案 SDK

.NET Core 和 .NET 5 和更新版本專案會與軟體發展工具組 (SDK) 相關聯。 每個 專案 SDK 都是一組 MSBuild 目標和 相關聯的 工作 ,負責編譯、封裝和發佈程式碼。 參考專案 SDK 的專案有時稱為 SDK 樣式專案

可用的 SDK

以下是可用的 SDK:

ID 描述 存放庫
Microsoft.NET.Sdk .NET SDK https://github.com/dotnet/sdk
Microsoft.NET.Sdk.Web .NET Web SDK https://github.com/dotnet/sdk
Microsoft.NET.Sdk.BlazorWebAssembly .NET Blazor WebAssembly SDK
Microsoft.NET.Sdk.Razor .NET Razor SDK
Microsoft.NET.Sdk.Worker .NET 背景工作服務 SDK
Microsoft.NET.Sdk.WindowsDesktop .NET Desktop SDK,其中包含 Windows Forms (WinForms) 和 Windows Presentation Foundation (WPF) 。* https://github.com/dotnet/winformshttps://github.com/dotnet/wpf

.NET SDK 是適用于 .NET 的基底 SDK。 其他 SDK 會參考 .NET SDK,而與其他 SDK 相關聯的專案則具有所有 .NET SDK 屬性可供使用。 例如,Web SDK 取決於 .NET SDK 和 Razor SDK。

您也可以撰寫可透過 NuGet 散發的專屬 SDK。

* 從 .NET 5 開始,Windows Forms和 Windows Presentation Foundation (WPF) 專案應該指定 .NET SDK () Microsoft.NET.Sdk ,而不是 Microsoft.NET.Sdk.WindowsDesktop 。 針對這些專案,將 設定 TargetFrameworknet5.0-windowsUseWPFUseWindowsFormstrue 將會自動匯入 Windows 桌面 SDK。 如果您的專案以 .NET 5 或更新版本為目標並指定 Microsoft.NET.Sdk.WindowsDesktop SDK,您將會收到組建警告 NETSDK1137。

專案檔

.NET 專案是以 MSBuild 格式為基礎。 專案檔具有 C# 專案的 .csproj 等副檔名,而 F# 專案的 副檔名為 .fsproj ,則為 XML 格式。 MSBuild 專案檔的根項目是 Project 元素。 元素 Project 具有選擇性 Sdk 屬性,指定要使用的 SDK (和版本) 。 若要使用 .NET 工具並建置程式碼,請將 Sdk 屬性設定為 可用 SDK 資料表中的其中一個識別碼。

<Project Sdk="Microsoft.NET.Sdk">
  ...
</Project>

若要指定來自 NuGet 的 SDK,請在名稱結尾包含版本,或在 global.json 檔案中指定名稱和版本。

<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
  ...
</Project>

另一個指定 SDK 的方式是使用最上層 Sdk 元素:

<Project>
  <Sdk Name="Microsoft.NET.Sdk" />
  ...
</Project>

以下列其中一種方式參考 SDK 可大幅簡化 .NET 的專案檔。 評估專案時,MSBuild 會在專案檔頂端和 Sdk.targets 底部新增 的隱含匯 Sdk.props 入。

<Project>
  <!-- Implicit top import -->
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  ...
  <!-- Implicit bottom import -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

提示

在 Windows 電腦上,您可以在%ProgramFiles%\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk\Sdk\Sdk資料夾中找到Sdk.props和 Sdk.targets 檔案。

前置處理專案檔

當 MSBuild 使用 命令包含 dotnet msbuild -preprocess SDK 及其目標之後,您可以看到完整展開的專案。 命令的 dotnet msbuild前置處理參數會顯示要匯入的檔案、其來源,以及對組建的貢獻,而不需要實際建置專案。

如果專案有多個目標架構,請將命令的結果指定為 MSBuild 屬性,只將命令的結果放在一個架構上。 例如:

dotnet msbuild -property:TargetFramework=netcoreapp2.0 -preprocess:output.xml

預設包含和排除

預設會包含和排除Compile 專案內嵌資源和None 專案在 SDK 中。 不同于非 SDK .NET Framework專案,您不需要在專案檔中指定這些專案,因為預設值涵蓋最常見的使用案例。 此行為可讓專案檔變得更小且更容易視需要手動瞭解和編輯。

下表顯示 .NET SDK 中包含和排除哪些元素和 Glob

元素 包含 Glob 排除 Glob 移除 Glob
Compile **/*.cs (或其他語言延伸模組) **/*.user;**/*.*proj;**/*.sln;**/*.vssscc N/A
EmbeddedResource **/*.resx **/*.user;**/*.*proj;**/*.sln;**/*.vssscc N/A
None **/* **/*.user;**/*.*proj;**/*.sln;**/*.vssscc **/*.cs;**/*.resx

注意

./bin./obj 資料夾是由 $(BaseOutputPath)$(BaseIntermediateOutputPath) MSBuild 屬性工作表示,預設會從 Glob 中排除。 Excludes 是由 DefaultItemExcludes 屬性表示。

.NET Desktop SDK 對 WPF 有更多包含和排除專案。 如需詳細資訊,請參閱 WPF 預設值包含和排除

建置錯誤

如果您在專案檔中明確定義這些專案,您可能會收到類似下列的 「NETSDK1022」 組建錯誤:

包含重複的 ' Compile ' 專案。 根據預設,.NET SDK 會包含專案目錄中的 ' Compile ' 專案。 如果您想要在專案檔中明確包含這些專案,您可以將這些專案從專案檔中移除,或將 'EnableDefault Compile Items' 屬性設定為 'false'。

包含重複的 ' EmbeddedResource ' 專案。 根據預設,.NET SDK 會包含專案目錄中的 ' EmbeddedResource ' 專案。 如果您想要在專案檔中明確包含這些專案,您可以將這些專案從專案檔中移除,或將 'EnableDefault EmbeddedResource Items' 屬性設定為 'false'。

若要解決錯誤,請執行下列其中一項:

  • 移除與上表所列之隱含專案相符的明確 CompileEmbeddedResourceNone 專案。

  • EnableDefaultItems 屬性 設定為 false ,以停用所有隱含檔案包含:

    <PropertyGroup>
      <EnableDefaultItems>false</EnableDefaultItems>
    </PropertyGroup>
    

    如果您想要指定要與應用程式一起發佈的檔案,您仍然可以使用該專案的已知 MSBuild 機制,例如 Content 元素。

  • EnableDefault Items、EnableDefault Compile ItemsEnableDefault EmbeddedResourceNone Items屬性設定為 false ,選擇性地停用 CompileEmbeddedResourceNone 或 Glob:

    <PropertyGroup>
      <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
      <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
      <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
    </PropertyGroup>
    

    如果您只停用 Compile Glob,Visual Studio 中的方案總管仍會顯示 *.cs 專案作為 None 專案的一部分,並包含在專案中。 若要停用隱含 None Glob,請設定 EnableDefaultNoneItemsfalse

隱含 using 指示詞

從 .NET 6 開始,隱含global using 指示詞會新增至新的 C# 專案。 這表示您可以使用這些命名空間中定義的類型,而不需要指定其完整名稱或手動新增 using 指示詞。 隱含層面是指 global using 指示詞會新增至專案obj目錄中產生的檔案。

針對使用下列其中一個 SDK 的專案,會新增隱含 global using 指示詞:

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Worker
  • Microsoft.NET.Sdk.WindowsDesktop

global using系統會針對以專案 SDK 為基礎的一組預設命名空間中的每個命名空間新增 指示詞。 下表顯示這些預設命名空間。

SDK 預設命名空間
Microsoft.NET.Sdk System
System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading
System.Threading.Tasks
Microsoft.NET.Sdk.Web System.Net.Http.Json
Microsoft.AspNetCore.Builder
Microsoft.AspNetCore.Hosting
Microsoft.AspNetCore.Http
Microsoft.AspNetCore.Routing
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
Microsoft.NET.Sdk.Worker Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
Microsoft.NET.Sdk.WindowsDesktop (Windows Forms) Microsoft.NET.Sdk 命名空間
System.Drawing
System.Windows.Forms
Microsoft.NET.Sdk.WindowsDesktop (WPF) Microsoft.NET.Sdk 命名空間
刪除 System.IO
刪除 System.Net.Http

如果您想要停用此功能,或想要在現有的 C# 專案中啟用隱含 global using 指示詞,您可以透過ImplicitUsings MSBuild 屬性來執行此動作。

您可以將 Visual Basic) 專案的專案 (或 Import 專案新增 Using 至專案檔,以指定其他隱含 global using 指示詞,例如:

<ItemGroup>
  <Using Include="System.IO.Pipes" />
</ItemGroup>

隱含套件參考

以 .NET Core 1.0 - 2.2 或 .NET Standard 1.0 - 2.0 為目標時,.NET SDK 會新增特定 中繼套件的隱含參考。 中繼套件是以架構為基礎的套件,只包含其他套件的相依性。 中繼套件會根據專案檔的 TargetFrameworkTargetFrameworks 屬性中指定的目標 framework (s) 隱含參考。

<PropertyGroup>
  <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup>
  <TargetFrameworks>netcoreapp2.1;net462</TargetFrameworks>
</PropertyGroup>

如有需要,您可以使用 DisableImplicitFrameworkReferences 屬性來停用隱含套件參考,並只將明確參考新增至您需要的架構或套件。

建議:

  • 以.NET Framework為目標時,.NET Core 1.0 - 2.2 或 .NET Standard 1.0 - 2.0 不會透過專案檔中的專案,將明確參考新增至 Microsoft.NETCore.AppNETStandard.Library 中繼套件 <PackageReference> 。 針對 .NET Core 1.0 - 2.2 和 .NET Standard 1.0 - 2.0 專案,這些中繼套件會隱含參考。 對於.NET Framework專案,如果使用 .NET Standard 型 NuGet 套件時需要的任何 版本 NETStandard.Library ,NuGet 會自動安裝該版本。
  • 如果您需要以 .NET Core 1.0 - 2.2 為目標的特定執行時間版本,請在專案中使用 <RuntimeFrameworkVersion> 屬性 (例如, 1.0.4) 而不是參考中繼套件。 例如,如果您使用 獨立部署,您可能需要特定修補程式版本 1.0.0 LTS 執行時間。
  • 如果您以 .NET Standard 1.0 - 2.0 為目標時需要特定版本的 NETStandard.Library 中繼套件,您可以使用 <NetStandardImplicitPackageVersion> 屬性並設定您需要的版本。

建置事件

在 SDK 樣式專案中,使用名為 或 的 PreBuild MSBuild 目標,並設定 BeforeTargets 的 屬性 PreBuildAfterTargetsPostBuild 屬性。 PostBuild

<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="&quot;$(ProjectDir)PreBuildEvent.bat&quot; &quot;$(ProjectDir)..\&quot; &quot;$(ProjectDir)&quot; &quot;$(TargetDir)&quot;" />
</Target>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
   <Exec Command="echo Output written to $(TargetDir)" />
</Target>

注意

  • 您可以針對 MSBuild 目標使用任何名稱。 不過,Visual Studio IDE 會 PreBuild 辨識和 PostBuild 目標,因此,您可以使用這些名稱來編輯 IDE 中的命令。
  • SDK 樣式專案中不建議使用 和 屬性 PreBuildEventPostBuildEvent ,因為 這類 $(ProjectDir) 宏不會解析。 例如,不支援下列程式碼:
<PropertyGroup>
  <PreBuildEvent>"$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"</PreBuildEvent>
</PropertyGroup>

自訂群組建

有各種方式可以 自訂群組建。 您可以將屬性當做引數傳遞至 msbuilddotnet 命令,以覆寫屬性。 您也可以將 屬性新增至專案檔或 Directory.Build.props 檔案。 如需 .NET 專案的實用屬性清單,請參閱 .NET SDK 專案的 MSBuild 參考

自訂目標

.NET 專案可以封裝自訂 MSBuild 目標和屬性,以供取用套件的專案使用。 當您想要下列情況時,請使用這種類型的擴充性:

  • 擴充建置程式。
  • 存取建置程式的成品,例如產生的檔案。
  • 檢查叫用組建所在的組態。

您可以在表單 <package_id>.targets<package_id>.props (中放置檔案,以新增自訂建置目標或屬性,例如, Contoso.Utility.UsefulStuff.targets) 專案 置資料夾中。

下列 XML 是 .csproj 檔案中的程式碼片段,指示 dotnet pack 命令要封裝的內容。 元素會將 <ItemGroup Label="dotnet pack instructions"> 目標檔案放在封裝內的 組建 資料夾中。 元素 <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles"> 會將元件和 .json 檔案放在 組建 資料夾中。

<Project Sdk="Microsoft.NET.Sdk">

  ...
  <ItemGroup Label="dotnet pack instructions">
    <Content Include="build\*.targets">
      <Pack>true</Pack>
      <PackagePath>build\</PackagePath>
    </Content>
  </ItemGroup>
  <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles">
    <!-- Collect these items inside a target that runs after build but before packaging. -->
    <ItemGroup>
      <Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
        <Pack>true</Pack>
        <PackagePath>build\</PackagePath>
      </Content>
    </ItemGroup>
  </Target>
  ...

</Project>

若要在專案中取用自訂目標,請新增 PackageReference 指向套件及其版本的元素。 不同于工具,自訂目標套件包含在取用專案的相依性關閉中。

您可以設定如何使用自訂目標。 因為它是 MSBuild 目標,所以它可以相依于指定的目標、在另一個目標之後執行,或使用 命令手動叫用 dotnet msbuild -t:<target-name> 。 不過,若要提供更好的使用者體驗,您可以結合個別專案工具和自訂目標。 在此案例中,每個專案工具會接受任何必要參數,並將它轉譯為執行目標的必要 dotnet msbuild 調用。 您可以在 dotnet-packer 專案中的 MVP Summit 2016 Hackathon 範例儲存機制,查看此類協同作用範例。

另請參閱