.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 Worker 服務 SDK
Microsoft.NET.Sdk.WindowsDesktop .net桌面 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。

您也可以撰寫自己的 SDK,以透過 NuGet 來散發。

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

專案檔

.net 專案是以MSBuild格式為基礎。 Project 檔案(具有適用于 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.props 頂端和底部加入隱含的匯入 Sdk.targets

<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 資料夾中找到 .propssdk .targets 檔案。

前置處理專案檔

您可以看到完全展開的專案,MSBuild 在 SDK 之後看到它,並使用命令來包含其目標 dotnet msbuild -preprocess 。 命令的前置 處理參數 會顯示要匯入的檔案 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 MSBuild 屬性所表示的和資料夾, $(BaseOutputPath) $(BaseIntermediateOutputPath) 預設會從 glob 中排除。 [排除] 會以 DefaultItemExcludes 屬性表示。

.NET 桌面 SDK 有更多包含和排除的 WPF。 如需詳細資訊,請參閱 WPF 預設包含和排除

建置錯誤

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

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

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

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

  • 移除符合上 Compile EmbeddedResource 表所 None 列之隱含專案的明確、或專案。

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

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

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

  • Compile EmbeddedResource None 由將 EnableDefault Compile ItemsEnableDefault EmbeddedResource ItemsEnableDefault None Items 屬性設為,選擇性地停用、或 glob false

    <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 目錄中產生的檔案的事實。

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

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft NET.TCP。
  • 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.TCP。 Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
WindowsDesktop (Windows Forms) Microsoft. Sdk 命名空間
System.Drawing
System.Windows.Forms
WindowsDesktop (WPF) Microsoft. Sdk 命名空間
刪除 System.IO
刪除 System.Net.Http

如果您想要停用這項功能,或想要 global using 在現有的 c # 專案中啟用隱含指示詞,您可以透過 ImplicitUsings MSBuild 屬性來這麼做。

您可以藉由為 global using Using 專案檔) 的 Visual Basic 專案加入專案 (或專案,來指定其他隱含指示詞 Import ,例如:

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

隱含套件參考

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

<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 專案,如果 NETStandard.Library 使用以 .NET Standard 為基礎的 NuGet 套件時需要任何版本,NuGet 會自動安裝該版本。
  • 如果您需要將目標設為 .NET Core 1.0-2.2 的特定執行階段版本,請使用 <RuntimeFrameworkVersion> 專案中的屬性 (例如, 1.0.4) ,而不是參考中繼套件。 例如,如果您使用的是 獨立部署,則可能需要1.0.0 版 LTS 執行時間的特定修補程式版本。
  • 如果您在以 NETStandard.Library .NET Standard 1.0-2.0 為目標時需要特定版本的中繼套件,您可以使用 <NetStandardImplicitPackageVersion> 屬性並設定所需的版本。

建置事件

在 SDK 樣式專案中,使用名為或的 MSBuild 目標, PreBuild PostBuild 並設定的 BeforeTargets 屬性 PreBuild 或的 AfterTargets 屬性 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 中編輯命令。
  • PreBuildEvent PostBuildEvent 在 SDK 樣式專案中不建議使用屬性,因為不會解析像這樣的宏 $(ProjectDir) 。 例如,不支援下列程式碼:
<PropertyGroup>
  <PreBuildEvent>"$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"</PreBuildEvent>
</PropertyGroup>

自訂群組建

自訂群組建的方式有很多種。 您可以藉由將屬性做為引數傳遞至 msbuilddotnet 命令,來覆寫該屬性。 您也可以將屬性加入至專案檔或 .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 範例儲存機制,查看此類協同作用範例。

另請參閱