本指南應該適用於大多數 .NET 專案類型。 這些步驟已經在主控台和 UI 專案(如 WPF)中測試過。 想看工作範例,可以參考 samples 資料夾裡的
dotnet-app (控制台)和wpf-app (WPF)樣本。
本指南示範如何在 .NET 應用程式中使用 winapp CLI 來除錯,並以套件身份碼子將應用程式打包為 MSIX。
套件身份是 Windows app 模型中的核心概念。 它讓你的應用程式能存取特定的 Windows API(例如通知、安全、AI API 等)、乾淨安裝/卸載體驗等等。
標準執行檔(例如用 dotnet build建立的)沒有套件身份。 本指南說明如何新增它用於除錯,然後再打包以供發佈。
先決條件
.NET SDK:安裝.NET SDK(安裝後需重新啟動):
winget install Microsoft.DotNet.SDK.10 --source wingetWinapp CLI:透過 Winget 安裝工具
winapp(若已安裝則更新):winget install Microsoft.winappcli --source winget
1. 建立一個新的 .NET 應用程式
先建立一個簡單的 .NET 主控台應用程式:
dotnet new console -n dotnet-app
cd dotnet-app
執行它以確保一切正常:
dotnet run
輸出應該是「哈囉,世界!」
2. 更新代碼以驗證身份
我們會更新應用程式,以檢查它是否運行於具有套件識別的狀態。 我們將使用 Windows 執行階段 API 來存取套件 API。
首先,更新你的 project 檔案,針對特定的 Windows SDK 版本。 打開 dotnet-app.csproj,並將 TargetFramework 改為包含 Windows SDK 版本:
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
這讓你能在不需要額外套件的情況下存取 Windows 執行階段 API。
現在將Program.cs的內容替換為以下程式碼。 此程式碼嘗試使用 Windows 執行階段 API 取得目前的套件識別碼。 若成功,則會列印封包族名;否則,會顯示「未包裝」。
using Windows.ApplicationModel;
try
{
var package = Package.Current;
var familyName = package.Id.FamilyName;
Console.WriteLine($"Package Family Name: {familyName}");
}
catch (InvalidOperationException)
{
// Thrown when app doesn't have package identity
Console.WriteLine("Not packaged");
}
3. 無身份運行
現在,照常執行應用程式:
dotnet run
你應該會看到輸出「未打包」。 這確認了標準執行檔在沒有任何套件身份的情況下執行。
4. 使用 Winapp CLI 初始化 Project
winapp init 指令會自動偵測 .csproj 檔案,並執行針對 .NET 的設定。 它一次設定你需要的所有東西:驗證你的 TargetFramework、新增所需的 NuGet 套件、產生應用程式清單,以及資產。
執行以下指令並依照提示操作:
winapp init
出現提示時:
- 套件名稱:按 Enter 接受預設(dotnet-app)
- Publisher name:按 Enter 接受預設或輸入你的名字
- 版本:按下 "Enter" 以接受 1.0.0.0
- Description:按 Enter 接受預設(Windows 應用程式)或輸入描述
- Windows 應用程式 SDK setup:選擇穩定、預覽或實驗(決定新增哪個Windows 應用程式 SDK版本)
-
TargetFramework 更新:如果你的
TargetFramework沒有支援的 Windows SDK 版本,系統會提示你更新(例如,更新到net10.0-windows10.0.26100.0) - 開發者模式:如果系統提示你要開啟「開發者模式」,你可以選擇開啟,但請注意這需要管理員權限
這個命令將會執行以下作業:
- 如有需要,請將
TargetFramework中的.csproj更新為受支援的 Windows TFM。 - 將
Microsoft.WindowsAppSDK、Microsoft.Windows.SDK.BuildTools和Microsoft.Windows.SDK.BuildTools.WinAppNuGet 套件參考新增到你的.csproj中 - 建立
Package.appxmanifest資料夾及Assets資料夾,以用作應用程式識別。
備註
與原生/C++ 專案不同,.NET 流程不會產生一個 winapp.yaml 檔案。 NuGet 套件是直接透過你的.csproj 進行管理。 用 dotnet restore 來還原複製後的套件。
你可以開啟 Package.appxmanifest 來進一步自訂屬性,例如顯示名稱、發佈者和功能。
為了確認套件是否已加入您的專案:
dotnet list package
你應該會在輸出中看到Microsoft.WindowsAppSDK和Microsoft.Windows.SDK.BuildTools。
新增執行別名(用於控制台應用程式)
因為我們正在打造一個主控台應用程式,我們需要確保 dotnet run 主控台輸出一直存在目前的終端機中。 預設情況下,dotnet run 透過 AUMID 啟用啟動已封裝的應用程式,開啟一個新視窗(當主控台應用程式結束時,該視窗會立即關閉,擷取所有輸出)。
要解決這個問題,你可以在 manifest 中加入執行別名,並告訴執行整合必須用該別名啟動。
如果你正在做 UI 應用程式(WPF、WinForms、WinUI),可以跳過這個步驟。 這些應用程式會自行渲染視窗,所以預設的 AUMID 啟動才是你想要的。
將執行別名加入到您的配置檔案中:
winapp manifest add-alias這會新增一個
uap5:ExecutionAlias到Package.appxmanifest(預設使用你專案的執行檔名稱),讓應用程式可以從終端機以名稱啟動。告訴整合系統
dotnet run使用別名。 打開dotnet-app.csproj並在任意<PropertyGroup>內容中加入以下內容(或必要時新增<PropertyGroup>):<WinAppRunUseExecutionAlias>true</WinAppRunUseExecutionAlias>設定這個屬性後,
dotnet run會透過執行別名啟動應用程式,並繼承當前終端機的 stdin/stdout/stderr,這樣你就能直接看到控制台的輸出結果。
5. 利用身份驗證除錯
由於 winapp init 將 Microsoft.Windows.SDK.BuildTools.WinApp NuGet 套件加入你的專案,你可以直接執行:
dotnet run
這會自動在底層調用 winapp run——建立一個鬆散型封裝,向 Windows 註冊,並以完整封裝身份啟動您的應用程式。
備註
你可能會看到關於套件來源的 NuGet 漏洞警告(NU1900)。 這些可放心忽略——不會影響你的專案建置。
你應該會看到類似的輸出:
Package Family Name: dotnet-app_12345abcde
這能確認你的應用程式是以有效的套件身份執行!
替代方案:手動 winapp run
如果你沒用 winapp init 過(或移除了 NuGet 套件),你可以手動編譯並執行:
dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0
要重新加入 NuGet 套件:dotnet add package Microsoft.Windows.SDK.BuildTools.WinApp --prerelease
小提示
要停用自動 dotnet run 整合,請將 <EnableWinAppRunSupport>false</EnableWinAppRunSupport> 加入到你的 .csproj。 請參閱 dotnet run 支援文件 以瞭解自訂選項。
替代方案:Sparse 封裝識別
如果你特別需要稀疏套件的行為(不複製檔案的識別),你可以改用 create-debug-identity。 這樣會偵測到一個稀疏的套件指向你的 exe,而不是建立鬆散的版面配置:
winapp create-debug-identity .\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe
接著直接執行執行檔(不要使用 dotnet run ,因為可能會重建或覆蓋檔案):
.\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe
替代方案:手動執行 MSBuild 的目標
如果你不想用 NuGet 套件,可以新增一個自訂的 MSBuild 目標,讓它在除錯建置後執行 create-debug-identity 。 將此加到你的 .csproj 檔案末尾,緊接於關閉的 </Project> 標籤之前:
<!-- Automatically apply debug identity after Debug builds -->
<Target Name="ApplyDebugIdentity" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
<Exec Command="winapp create-debug-identity "$(TargetDir)$(TargetName).exe""
WorkingDirectory="$(ProjectDir)"
IgnoreExitCode="false" />
</Target>
用這個設定, dotnet build 套用除錯身份,然後你可以直接執行執行檔。 請注意,dotnet run可能會重建並覆蓋其識別,因此建置後請手動執行exe。
小提示
關於進階除錯工作流程(附加除錯器、IDE 設定、啟動除錯),請參閱 除錯指南。
何時跳過:如果你偏好明確控制身份的適用時間,或你大部分開發週期都不需要身份的程式碼,上述手動方式可能更簡單。
6. 使用 Windows 應用程式 SDK(可選)
Windows 應用程式 SDK 讓你能使用超越基礎 Windows SDK 的現代 Windows API——像是通知系統、視窗 API、應用程式生命週期管理,以及裝置內建 AI。 如果你的應用程式需要這些功能,這步驟非常適合你。 如果您只需要發佈時的套件識別,可跳至步驟 7。
如果你執行了 winapp init(步驟 4),Microsoft.WindowsAppSDK 已作為 NuGet 套件參考被添加到你的 .csproj。 你可以用 dotnet list package來驗證。 如果你在 init 時跳過了 SDK 設定,或需要手動新增,請執行:
dotnet add package Microsoft.WindowsAppSDK
更新 Program.cs
將 Program.cs 的全部內容替換為以下程式碼,新增一個Windows 應用程式執行時版本檢查:
using Windows.ApplicationModel;
class Program
{
static void Main(string[] args)
{
try
{
var package = Package.Current;
var familyName = package.Id.FamilyName;
Console.WriteLine($"Package Family Name: {familyName}");
// Get Windows App Runtime version using the API
var runtimeVersion = Microsoft.Windows.ApplicationModel.WindowsAppRuntime.RuntimeInfo.AsString;
Console.WriteLine($"Windows App Runtime Version: {runtimeVersion}");
}
catch (InvalidOperationException)
{
// Thrown when app doesn't have package identity
Console.WriteLine("Not packaged");
}
}
}
建置並執行
重新建置並使用 Windows 應用程式 SDK 執行應用程式。 既然我們已經加入了 WinAppSDK,就需要以身份重新註冊,以便 winapp 增加運行時的依賴。 如果你新增了 WinApp NuGet 套件(建議),只要執行 dotnet run。 否則(請替換 dotnet-app 成你的專案名稱):
dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0
你現在應該會看到輸出如下:
Package Family Name: dotnet-app.debug_12345abcde
Windows App Runtime Version: 8000.770.947.0
Windows 應用程式 SDK NuGet 套件包含所有存取現代 Windows API 所需的組件,包括:
- 通知和動態磁磚
- 視窗與應用程式生命週期
- 即時通知
- 以及更多 Windows 應用程式 SDK 元件
想了解更進階的Windows 應用程式 SDK使用,請參考 Windows 應用程式 SDK 文件。
7. MSIX 封裝
當你準備好發佈應用程式時,可以用相同的清單打包成 MSIX。
發佈用的建置
首先,將應用程式建置在發佈模式以達到最佳效能:
dotnet build -c Release
備註
你可能會看到 NuGet 漏洞警告(NU1900)。 這些可以忽略,並不會影響你的編譯結果。
產生開發證書
在包裝前,你需要一份開發證書才能簽名。 如果你還沒生成,請生成一個:
winapp cert generate --if-exists skip
簽名與包裝
現在你可以包裝並簽名了。 將 pack 指令指向你的建置輸出資料夾(將 dotnet-app 和 TFM 路徑替換為你專案中的實際值):
# package and sign the app with the generated certificate
winapp pack .\bin\Release\net10.0-windows10.0.26100.0 --manifest .\Package.appxmanifest --cert .\devcert.pfx
注意:指令會
pack自動從你目前的目錄中使用Package.appxmanifest,並在打包前將其複製到目標資料夾。 產生的 .msix 檔案會放在目前的目錄中。
安裝憑證
在安裝 MSIX 套件之前,你需要先安裝開發憑證。 請以管理員身份執行此指令:
winapp cert install .\devcert.pfx
安裝並執行
透過雙擊產生的 *.msix 檔案安裝套件。
現在你可以在終端機的任何地方輸入以下關鍵字來執行應用程式:
dotnet-app
你應該會看到「Package Family Name」的輸出,確認它已安裝並以身份執行。
小提示
如果你需要重新打包應用程式(例如程式碼變更後),在再次執行winapp pack前,先在你的Package.appxmanifest中增加Version。 Windows 需要更高的版本號才能更新已安裝的套件。
Tips
- 一旦準備好分發,你可以用憑證授權中心的程式碼簽署憑證來簽署 MSIX,讓使用者不必安裝自簽憑證。
- Microsoft Store 會幫你簽署 MSIX,提交前不需要簽名。
- 你可能需要建立多個 MSIX 套件,分別針對你支援的架構(x64、Arm64)。 使用
-r旗標以dotnet build鎖定特定架構:dotnet build -c Release -r win-x64或dotnet build -c Release -r win-arm64。
自動化 MSIX 封裝(選用)
若要在 Release 建置中自動化 MSIX 封裝,請將此目標加入檔案 .csproj (你可以與除錯身份目標一同加入):
<!-- Automatically package as MSIX after Release builds -->
<Target Name="PackageMsix" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
<!-- Package and sign directly from build output -->
<Exec Command="winapp pack "$(TargetDir.TrimEnd('\'))" --cert "$(ProjectDir)devcert.pfx""
WorkingDirectory="$(ProjectDir)"
IgnoreExitCode="false" />
</Target>
在此配置下:
- 將專案以 Release 模式
dotnet build -c Release建置,會自動建立 MSIX 套件 - MSIX 將使用您的開發憑證進行打包和簽署
- 最終
.msix檔案會放在專案根目錄中
你也可以透過修改條件為 PackagedRelease來建立自訂配置(例如 '$(Configuration)' == 'PackagedRelease')。
後續步驟
- 透過 winget 發佈:請將您的 MSIX 提交至 Windows 封裝管理員 社群倉庫
-
發佈至Microsoft Store:請使用
winapp store提交您的套件 -
設定 CI/CD:使用
setup-WinAppCliGitHub Action 在管線中自動化打包 - 探索Windows API:透過套件身份,你現在可以使用Notifications、on-device AI,以及其他依賴 身份相關的 API