Windows 上的管理式 .NET 安裝

部分移除的 .NET 安裝是像 Microsoft Defender 弱點管理 這類漏洞掃描軟體報告裝置的常見原因。 了解 .NET 安裝的運作方式,有助於管理員調查報告並採取補救措施。

在 Windows 上,.NET 元件如執行時和 SDK 由多個 MSI 組成。 個別 MSI 不會直接分發。 相反地,它們會被鎖在一起,形成束狀。

在 Windows 上取得 .NET

  • 獨立套件(EXE)可從 .NET 網站下載。
  • WinGet 提供包含 .NET 套件的套件。
  • 服務更新透過 Microsoft Update 的自動更新、WSUS 及 Windows Update 目錄來分發套件。
  • 獨立軟體供應商(ISV)可能會將 .NET 套件重新分發為其軟體的一部分。
  • OEM 有時會在新裝置的出廠映像中預先安裝 .NET 套件。
  • 部分 Azure 市集的 Windows 映像檔包含預裝的套件副本。
  • 像 Chocolatey 這類第三方套件管理器也會分發 .NET 套件。
  • 企業有時會用專有套件重新打包這些套件進行內部分發。
  • 部分 .NET 應用程式主機也會指示使用者下載並安裝缺少的執行時套件。

Visual Studio 也可用來取得 .NET,並使用與獨立套件相同的 MSI。

Note

.NET SDK 套件隨 Visual Studio 一同附帶到 16.2。 從 .NET Core 3.0 在 Visual Studio 16.3 開始,SDK 套件被個別的 .NET MSI 取代。

Upgrades

.NET 支援在主要/次要版本內的補丁版本間進行升級。 .NET 8.0.7 會升級先前的版本,如 8.0.4 或 8.0.0,包括預發布版本,但不會升級像 .NET 7.0 這類先前的主要版本。 .NET SDK 支援在功能區間的補丁間升級。 8.0.100 SDK 可以升級到 8.0.103,但 8.0.3xx SDK 無法升級 1xx 或 2xx 功能頻段。

大多數升級都是在套裝層級處理。 舊版本只有在安裝新版本後才會被移除。 有兩個例外:.NET 主機與 ASP.NET Core 模組的 MSI 會即時更新。

從 .NET 8 開始,使用者可以選擇延後移除先前版本的套件。

叢的組成與參考計數

組合包由多個 MSI 組成,其中有些 MSI 在多個組合間共享。

.NET 安裝程式組成

  • 執行時套件包含三個 MSI,這些 MSI 也隨桌面執行時和 SDK 套件一起推出。
  • 桌面套件包含一個額外的 MSI,與 SDK 套件共享。
  • SDK 包含額外的 MSI,包含用於建立與建置 .NET 應用程式的 CLI、範本與目標套件。

共享的 MSI 是透過引用計數來管理的。 每個 .NET MSI 會建立一個稱為提供者金鑰的登錄檔金鑰,允許組合自行註冊為相依者。 如果已經安裝了 MSI,套件只會更新註冊資訊。 綁定包在移除時即為未註冊。 只有當沒有登記的受扶養人時,共享的 MSI 才會被移除。

以下登錄資訊是 .NET 主機 MSI 提供者金鑰的範例。 共有四個註冊的受扶養人,包括 Visual Studio。

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\Dotnet_CLI_SharedHost_10.0_x64
    (Default)   REG_SZ    {8A8CC49F-7D1E-45DC-B7B5-35FF61A2C25E}
    Version     REG_SZ    80.40.55332
    DisplayName REG_SZ    Microsoft .NET Host - 10.0.10 (x64)

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\Dotnet_CLI_SharedHost_10.0_x64\Dependents\VS.{AEF703B8-D2CC-4343-915C-F54A30B90937}

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\Dotnet_CLI_SharedHost_10.0_x64\Dependents\{609A456D-467D-4077-9BA2-B6404F1B1163}

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\Dotnet_CLI_SharedHost_10.0_x64\Dependents\{866BECDA-F284-473A-9E84-0CCE816BF06F}

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\Dotnet_CLI_SharedHost_10.0_x64\Dependents\{FD5EA214-C690-466F-B8FB-1741881913F9}

Note

當套件移除後,受扶養人仍註冊,例如卸載中斷,個別 MSI 會成為孤兒。

Note

Visual Studio 使用一個眾所皆知的值 VS.{AEF703B8-D2CC-4343-915C-F54A30B90937},來將自己註冊為相依者。 實際的參考數量是透過檢查每個 Visual Studio 實例的安裝清單來決定的。

Bin 部署的設施

Bin 部署安裝指的是與 MSI 無關聯的 .NET 副本。 這可以透過以管理員身份執行安裝腳本,並將安裝目錄設定為「Program Files\dotnet」來達成。 廢棄箱部署的安裝可能會使修復工作變得複雜。 掃描器會回報漏洞,但管理員找不到可卸載的 MSI。 DNIM 能夠偵測 bin 部署的安裝。

偵測

DNIM 依賴多種啟發式方法來識別與 .NET 相關的束與 MSI。 準確偵測安裝對成功修復非投訴設備至關重要。

搭售方案

套件的識別方式是透過其顯示名稱及儲存在登錄檔中的檔案資訊來識別。 執行檔還會進行額外檢查,以確保其安裝檔的有效性。 這些資訊也會與 .NET 為每個版本發布的 JSON 資料做比較。

MSI 偵測

DNIM 會對儲存在下方HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components登錄檔中的安裝元件資料進行全面搜尋,以識別 .NET MSI。

每個子金鑰代表不同的元件 ID。 每個鍵下的數值代表產品代碼。 元件 ID 與產品代碼皆以打包 GUID 形式儲存。 以下範例為與 dotnet.exe相關的組件。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\BBB993545ADD68342A9E16F83B5CA481
    40A3E8A8CB38EDC4299598B366C6A11B    REG_SZ    C:\Program Files\dotnet\dotnet.exe
    A75437C333A10ED46B2CF6AB78E7F1FC    REG_SZ    C:\Program Files (x86)\dotnet\dotnet.exe
    79D2396D1F638B04C9CDAC38562B0100    REG_SZ    C:\Program Files\dotnet\dotnet.exe
    EA6D9CBF69367CF4CB81005882631FD6    REG_SZ    C:\Program Files (x86)\dotnet\dotnet.exe
    872D9C61B8AA60F47A4CDF137C8523A3    REG_SZ    C:\Program Files (x86)\dotnet\dotnet.exe
    6235DF10DB18AED4F910D396BBDD7AE5    REG_SZ    C:\Program Files\dotnet\dotnet.exe
    0370151E43A53FE48B564853D1B81FAB    REG_SZ    C:\Program Files\dotnet\dotnet.exe
    F6D22817F79056B46B45655C7495EE9A    REG_SZ    C:\Program Files (x86)\dotnet\dotnet.exe
    D512842CB6C6A404BAE605D564042E50    REG_SZ    C:\Program Files\dotnet\dotnet.exe

Bin 部署安裝

由於 DNIM 會對安裝元件進行詳盡搜尋,任何未與 MSI 相關的 Program Files\dotnet 檔案都會被歸類為已部署的安裝。

Classification

錯誤分類安裝可能導致移除或保留錯誤安裝,可能導致應用程式中斷或裝置處於不合規狀態。

一旦識別出產品(例如 NET 10),即可確定其發布(例如 10.0.4)及支援階段(例如啟用)等資訊。 這讓管理員能夠建立彈性的部署方案。

安裝依據其 .NET 元件(ASP.NET Core、SDK 等)、架構及安裝類型(套件、MSI 或 bin 部署)進一步分類。

有些特殊情況值得一提。

.NET 標準 2.1

確保行為一致,安裝必須定義其產品、發布及支援階段。 .NET Standard 2.1 的目標鎖定包帶來了有趣的挑戰。 它不包含可執行程式碼,僅提供標準定義的 API 參考組合。 該目標包最初作為 .NET Core 3.0.100 SDK 的一部分推出,但直到 .NET 10 前,所有 SDK 都包含在內。 雖然 DNIM 會將該版本與產品歸類為 .NET Core 3.0,但支援階段始終被報告為活躍,因為它可能包含在仍在積極支援中的 SDK。

Note

.NET Standard 2.1 目標套件在 .NET 10 的 SDK 安裝中被移除。 SDK 在建置應用程式時會自動使用 NuGet 套件下載缺少的目標包。

.NET SDK 功能頻帶

在 .NET Core 1.0 和 1.1 中,SDK 採用類似 runime 的版本管理方案。 .NET Core 1.1 的最後一個 SDK 版本為 1.1.14,包含 1.1.13 執行環境。

SDK 功能頻帶是在 2.1.100 SDK 中引入,用以區分 Visual Studio 支援的功能。 SDK 隨 .NET Core 2.0.5 版本隨之發行。 最後一個 2.0 SDK 版本為 2.1.202,並包含在 2.0.9 版本中。 第一個以 .NET Core 2.1 格式發佈的 SDK 版本為 2.1.300。 在後續版本中,SDK 功能頻帶總是從 100 開始,例如 2.2.100、3.0.100 等。