天天看點

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

什麼是Nuget

NuGet是Microsoft開發平台的程式集包管理器,它由用戶端工具和服務端站點組成,用戶端工具提供給使用者管理和安裝/解除安裝軟體程式包,以及打包和釋出程式包到NuGet服務端站點等功能,服務端站點存儲已經發行的軟體包,并為NuGet用戶端軟體包庫提供服務,使軟體包共享給其他的開發者。

适用于任何現代開發平台的基本工具可充當一種機制,通過這種機制,開發人員可以建立、共享和使用有用的代碼。通常,此類代碼捆綁到“包”中,其中包含編譯的代碼(如DLL)以及在使用這些包的項目中所需的其他内容。

對于.NET(包括.NET Core),共享代碼的Microsoft支援的機制則為NuGet ,其定義如何建立、托管和使用面向.NET的包,并針對每個角色提供适用工具。

簡單來說,NuGet 包是具有

.nupkg

擴充的單個ZIP檔案,此擴充包含編譯代碼(Dll)、與該代碼相關的其他檔案以及描述性清單(包含包版本号等資訊)。 使用代碼的開發人員共享建立包,并将其釋出到公用或專用主機。 包使用者從适合的主機擷取這些包,将它們添加到項目,然後在其項目代碼中調用包的功能。 随後,NuGet自身負責處理所有中間詳細資訊。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

由于NuGet支援公用

nuget.org

主機旁邊的專用主機,是以,可以使用NuGet包來共享組織或工作組專用的代碼。 此外,你還可以使用NuGet包作為一種便捷的方式,将自己的代碼用于除你自己項目之外的任何其他項目。 簡而言之,NuGet包是可共享的代碼單元,但不需要暗示任何特定的共享方式。

識别項目格式

NuGet适用于所有.NET項目。但是,項目格式(SDK樣式或非SDK樣式)決定了使用和建立NuGet包所需的一些工具和方法。SDK樣式的項目使用SDK屬性。确定項目類型非常重要,因為用于使用和建立NuGet包的方法和工具都依賴于項目格式。對于非SDK樣式的項目,方法和工具還取決于項目是否遷移到

PackageReference

格式。
項目類型 預設項目格式 CLI工具
.NET Standard SDK樣式 dotnet CLI
.NET Core SDK樣式 dotnet CLI
.NET Framework 非SDK樣式 nuget.exe CLI

手動識别

使用Visual Studio Code打開

*.csproj

,如果

Project

節點,存在屬性

Sdk

基本上就是SDK樣式的。

SDK樣式示例
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

</Project>
           
非SDK樣式示例
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
           

差異點

非SDK樣式

項目檔案夾,我們發現,它會有一個

Properties

檔案夾,裡面有個我們熟知的

AssemblyInfo.cs

記錄了這個項目的資訊。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// 有關程式集的一般資訊由以下
// 控制。更改這些特性值可修改
// 與程式集關聯的資訊。
[assembly: AssemblyTitle("ExampleWinforms")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ExampleWinforms")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// 将 ComVisible 設定為 false 會使此程式集中的類型
//對 COM 元件不可見。如果需要從 COM 通路此程式集中的類型
//請将此類型的 ComVisible 特性設定為 true。
[assembly: ComVisible(false)]

// 如果此項目向 COM 公開,則下列 GUID 用于類型庫的 ID
[assembly: Guid("3f148d75-9dd3-4a79-b72d-a530b0bcbc7f")]

// 程式集的版本資訊由下列四個值組成: 
//
//      主版本
//      次版本
//      生成号
//      修訂号
//
//可以指定所有這些值,也可以使用“生成号”和“修訂号”的預設值
//通過使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
           

而在

SDK樣式

項目檔案夾,并不存在

Properties

檔案夾,項目資訊是直接記錄在

*.csproj

中的。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
    <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
    <Description>測試</Description>
    <Copyright>版權說明</Copyright>
    <PackageProjectUrl>https://www.baidu.com</PackageProjectUrl>
    <AssemblyVersion>1.0.0</AssemblyVersion>
    <FileVersion>1.0.0</FileVersion>
    <PackageReleaseNotes>發行說明</PackageReleaseNotes>
    <RepositoryUrl>git.xxxxxxxxxxxxxxxxxxxxxx</RepositoryUrl>
    <RepositoryType>git</RepositoryType>
    <Title>ExampleWinFormsApp</Title>
    <PackageId>ExampleWinFormsApp</PackageId>
    <Version>1.0.0</Version>
    <Authors>TaylorShi</Authors>
    <Company>TaylorShi Inc.</Company>
  </PropertyGroup>

</Project>
           

非SDK樣式項目打包

對于較為傳統的.Net framework的項目,它屬于非SDK樣式項目,是以對應的打包工具就是

nuget.exe

擷取Nuget.exe

NuGet.exe 5.0及更高版本需要

.NET Framework 4.7.2

或更高版本才能執行。

直接從

nuget.org

官方下載下傳一個即可。

  • nuget.exe

建議是丢

C:\Windows

目錄即可,省去配置什麼環境變量。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

Linux下安裝Nuget

sudo apt install mono-runtime
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

先安裝Mono 4.4.2+版本,然後執行如下指令:

sudo curl -o /usr/local/bin/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

編輯

~/.bash_aliases

或者

~/.bash_profile

,追加如下别名。

sudo vim ~/.bash_aliases
           
# Create as alias for nuget
alias nuget="mono /usr/local/bin/nuget.exe"
           

重新進入一次Shell,然後試試

nuget ?

來驗證安裝。

自我更新Nuget.exe

如果你之前已經安裝過它,還可以調用它自己的指令來更新它,因為前面我們放到

C:\Windows

目錄,是以這裡需要用管理者運作Windows Terminal。

nuget update -self
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

準備項目屬性

對非SDK樣式項目來說,它的項目屬性資訊是在

項目

-

屬性

-

程式集資訊

對話框中設定的,對應的檔案是

.\Properties\AssemblyInfo.cs

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

把這裡面能填的資訊都填下,程式集版本和檔案版本建議保持一緻,等下會作為Nuget包的版本号,前三位就行,最後一位可以是0。

建立Nuget初始清單

在目前這個

.csproj

目錄,執行如下指令:

nuget spec
           

它會針對

.csproj

這個項目生成一個初始清單,字尾為

*.nuspec

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

編輯補充初始清單

接下來我們可以使用Visual Studio Code,它剛開始的内容差不多是這樣:

<?xml version="1.0" encoding="utf-8"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <license type="expression">MIT</license>
    <!-- <icon>icon.png</icon> -->
    <projectUrl>http://project_url_here_or_delete_this_line/</projectUrl>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>$copyright$</copyright>
    <tags>Tag1 Tag2</tags>
  </metadata>
</package>
           

這裡面,有些如果有就填,沒有的話建議删除掉,比如:

  • projectUrl

    ,将包上傳到

    nuget.org

    時,字段

    projectUrl

    限制為4000個字元,如果有Github或者官網建議填下。
  • releaseNotes

    ,将包上傳到

    nuget.org

    時,字段

    releaseNotes

    限制為35,000個字元。
  • tags

    ,這個建議填一填,友善根據關鍵詞搜尋到。

接下來,我們可以給它弄個圖示,這樣好看點。

首先我們需要準備一個圖示檔案,比如就叫

icon.png

,把它放到

.csproj

目錄,官方建議是128x128的PNG或者JPEG格式,體積小于1MB。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

然後我們需要聲明這個圖示File檔案,比如:

<files>
  <file src=".\icon.png" target="images\" />
</files>
           

這裡

src

就填相對目錄就可以了,這個

target

其實有點像個命名空間,意味着這個png挂在

images\

下面了,是以在

<icon>

那裡應該寫成:

<icon>images\icon.png</icon>
           

如果你想要Nuget.org上呈現更精彩格式的說明,也可以内置一個markdown進來,先準備一個名為

readme.md

的檔案,裡面先随便寫點。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

然後以檔案形式加進來

<files>
  <file src=".\readme.md" target="docs\" />
</files>
           

readme

節點添加進來

<readme>docs\readme.md</readme>
           

最終效果:

<?xml version="1.0" encoding="utf-8"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <license type="expression">MIT</license>
    <icon>images\icon.png</icon>
    <readme>docs\readme.md</readme>
    <projectUrl>https://www.nuget.org/packages?q=Microsoft.Extensions.Logging</projectUrl>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>$copyright$</copyright>
    <tags>Microsoft TestPackage</tags>
  </metadata>
  <files>
    <file src=".\icon.png" target="images\" />
    <file src=".\readme.md" target="docs\" />
  </files>
</package>
           

生成Nuget包

在目前這個

.csproj

目錄,執行如下指令,它就會根據我們剛才

.nuspec

\Properties\AssemblyInfo.cs

的資訊結合起來,形成我們要的Nuget包。

nuget pack
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

最終效果有沒有達到預期,我們可以用離線Nuget包源來驗證下就知道了,方式後面會介紹。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

SDK樣式項目打包

擷取DotNet CLI

其實這個你裝了DotNet Core SDK的時候已經自帶了,可以執行指令驗證下:

dotnet --version
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

準備打包資訊

建立一個.Net Standard的類庫項目,并且添加到解決方案中:

dotnet new classlib --framework "netstandard2.0" -o netStandardLibrary
dotnet sln add .\netStandardLibrary\netStandardLibrary.csproj
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

對SDK風格的項目來說,一切都簡單了,打包資訊直接在

.csproj

檔案中,預設它可以是這樣子:

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

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

</Project>
           

接下來隻需要在

PropertyGroup

節點中來添加打包所需的資訊就是了。

<PackageId>netStandardLibrary</PackageId>
<Version>1.0.0</Version>
<Authors>Taylor</Authors>
<Company>Taylor Inc.</Company>
           

甚至還可以添加開關配置,這樣它預設就會生成Nuget包

<PropertyGroup>
  <PackRelease>true</PackRelease>
</PropertyGroup>
           

生成Nuget包

同樣的,還是在

.csproj

目錄,直接執行Dotnet CLI的指令即可:

dotnet pack -c Release
           
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

這時候在

.\bin\Release\netStandardLibrary.1.0.0.nupkg

就得到這個檔案了。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

釋出到Nuget.org

擷取Nuget.org密鑰

首先你需要準備一個微軟賬号,然後使用這個賬号來授權登入https://www.nuget.org即可,期間會讓你選一個名字注冊。

然後前往賬号菜單下的

API Keys

頁面。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

點選

Create

按鈕建立一個新的授權密鑰

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

其中

Key Name

随便填,但是

Glob Pattern

那裡可以填

*

,代表沒有限制,過期時間目前最長也就

365

天,然後點選

Create

按鈕即可。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

建立成功之後,就可以在

Manage

清單中看到它,這裡有一個

Copy

按鈕,點選它,并且妥善儲存好這個内容。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

這裡特别注意,這個

Copy

隻有一次機會,點選後就沒得點了,是以這個操作前往别犯糊塗。

推送到Nuget.org

這裡有個特别要注意的技巧,通過釋出多個包的時候,會存在依賴關系,我們應該将被依賴的包先釋出,再逐漸釋出後面的包。

推送到Nuget.org特别簡單,一句指令即可:

nuget push .\xxxxxxx.xxxxxxx.xxxxxxx.x.x.x.nupkg $ApiKey -Source https://api.nuget.org/v3/index.json
           

将其中

xxxxxxx.xxxxxxx.xxxxxxx.x.x.x.nupkg

替換成自己包的名稱即可,将

$ApiKey

替換成前面保管好的密鑰。

這裡如果你是要推送到自己的私有倉庫,隻需要把ApiKey和Source改成自己私有倉庫對應的即可。
乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

看到

Your package was pushed.

即表示釋出成功。

這時候前往Nuget官網或者在Visual Studio進入Nuget包管理就可以搜到它了(新包大概需要5-6分鐘建立索引)。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

離線安裝Nuget包

有時候,如果你在本地打包好了,但是不想釋出到包平台,其實也可以本地離線安裝,這個操作起來非常友善。

建立本地包源

打開Visual Studio頂部菜單中的

工具

-

Nuget包管理器

-

程式包管理器設定

進入Nuget包設定頁面。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

切換到左側

Nuget包管理器

-

程式包源

,在右上角找到

+

按鈕添加一個新的包源。

修改掉建立後的預設值,比如名稱可以改成

Local Package Source

,然後點選

那一行的

...

按鈕選擇放置了本地Nuget包的檔案夾,最後點選

更新

按鈕。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

使用本地包源

接下來,前往你要添加Nuget包的項目上右鍵,進入

管理Nuget程式包

菜單,進入

浏覽

界面,關鍵的一步是,切換最右側的包源為剛才添加的本地那個。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

這時候你就可以看到你本地的包了,你可以像平時一樣安裝即可。

乘風破浪,遇見最佳跨平台跨終端架構.Net Core/.Net生态 - 面向所有項目風格的Nuget打包釋出/離線部署(.NET Framework、.NET Standard)

不過需要注意的是,如果你安裝的包如果對其他包存在依賴,那麼你可能需要先安裝依賴包,也許這個依賴包是公開包源的,需要先切回如

Nuget.org

等線上包源。

參考

  • https://github.com/TaylorShi/HelloNugetPackage
  • NuGet簡介
  • 安裝NuGet用戶端工具
  • 快速入門:使用 Visual Studio 建立和釋出包(.NET Framework、Windows)
  • 使用dotnet CLI建立NuGet包
  • 辨別項目格式
  • .NET Framework生成NuGet包
  • C# NuGet打包和離線安裝
  • Visual Studio NuGet離線安裝
  • 共享你的控件 -- 用NuGet包裝自己的控件
  • .NET Framework生成NuGet包
  • https://www.nuget.org
  • .NET SDK項目的MSBuild引用
  • .nuspec引用
  • 快速入門:建立和釋出包 (dotnet CLI)

繼續閱讀