dotnet-msix について
dotnet-msixは、.NETデスクトップアプリ開発者向けのMSIXパッケージングスキルです。パッケージ作成、署名、配布、更新、CIビルドを扱い、単一プロジェクトとWAPプロジェクトの両方に対応します。
主な機能
- 01csprojまたはWAPからMSIXを作成
- 02証明書署名の設定
- 03Store提出とサイドロード配布
- 04App Installer更新の設定
- 05複数アーキテクチャのバンドル作成
- 06CI/CDへのMSIX手順追加
活用シーン
- 01.NETデスクトップアプリのリリースパッケージ作成
- 02配布用の証明書署名設定
- 03自動更新付きの直接配布設定
- 04複数アーキテクチャ向けパッケージ作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-msixインストール後、Claude Code で/dotnet-msixを入力して読み込まれたか確認します。
詳細
dotnet-msix
.NET デスクトップアプリケーション向けの MSIX パッケージングパイプライン:csproj(WindowsPackageType)および WAP プロジェクトからのパッケージ作成、証明書による署名(開発用の自己署名、本番用の信頼された CA、Microsoft Store による署名)、配布チャネル(Microsoft Store への提出、App Installer によるサイドローディング、SCCM/Intune を使用したエンタープライズ展開)、自動更新の設定(App Installer XML、バージョンチェック、差分更新)、複数アーキテクチャ向けの MSIX バンドル形式(.msixbundle)、CI/CD の MSIX ビルド手順。
バージョンの前提条件: Windows App SDK 1.6 以降(現在の安定版)。Windows App SDK で MSIX を使用する場合、Windows 10 ビルド 19041 以降が最小要件です。App Installer の自動更新プロトコルには Windows 10 ビルド 1709 以降が必要です。.NET 8.0 以降を基準とします。
スコープの境界: このスキルが扱うのは、MSIX パッケージングパイプライン(作成、署名、配布、Store への提出、自動更新、CI ビルド手順)です。WinUI 3 プロジェクトのセットアップ、XAML のパターン、パッケージ化と非パッケージ化のデプロイモードの比較は、[skill:dotnet-winui] が扱います。一般的な Native AOT コンパイル(PublishAot、ILLink 記述子)は、[skill:dotnet-native-aot] が扱います。一般的な CI/CD パイプラインのパターンは、[skill:dotnet-gha-patterns] と [skill:dotnet-ado-patterns] が扱います。
対象外: WinUI 3 プロジェクトのセットアップと MSIX と非パッケージ化の比較については、[skill:dotnet-winui] を参照してください。Native AOT の MSBuild 設定については、[skill:dotnet-native-aot] を参照してください。一般的な CI/CD パイプラインのパターンについては、[skill:dotnet-gha-patterns] と [skill:dotnet-ado-patterns] を参照してください。一般的な NuGet パッケージングについては、[skill:dotnet-nuget-authoring] を参照してください。コンテナーを使用したデプロイについては、[skill:dotnet-containers] を参照してください。
相互参照:[skill:dotnet-winui](WinUI プロジェクトのセットアップとパッケージングモードの比較)、[skill:dotnet-native-aot](AOT と MSIX のシナリオ)、[skill:dotnet-gha-patterns](CI パイプラインの構成)、[skill:dotnet-ado-patterns](ADO パイプラインの構成)、[skill:dotnet-nuget-authoring](NuGet パッケージング)。
MSIX パッケージの作成
csproj からの作成(単一プロジェクトのパッケージング)
最新の WinUI 3 アプリと Windows App SDK アプリでは、別の Windows Application Packaging(WAP)プロジェクトを作成せずに、アプリケーションの .csproj から MSIX パッケージを直接生成できます。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<UseWinUI>true</UseWinUI>
<WindowsPackageType>MSIX</WindowsPackageType>
<AppxPackageDir>$(SolutionDir)AppPackages\</AppxPackageDir>
<GenerateAppxPackageOnBuild>false</GenerateAppxPackageOnBuild>
</PropertyGroup>
</Project>
MSIX パッケージをビルドします。
# Build MSIX package
dotnet publish --configuration Release --runtime win-x64 \
/p:GenerateAppxPackageOnBuild=true \
/p:AppxPackageSigningEnabled=false
# Output: AppPackages\MyApp_1.0.0.0_x64.msix
WAP プロジェクト(Desktop Bridge)
WinUI 以外のデスクトップアプリ(WPF、WinForms)を MSIX としてラップするには、Windows Application Packaging Project を使用します。WAP プロジェクト(.wapproj)は Visual Studio の「Windows Application Packaging Project」テンプレートから作成します。標準の Microsoft.NET.Sdk ではなく、専用のプロジェクト形式を使用します。
重要な設定は、デスクトップアプリのプロジェクトを参照することです。
<ItemGroup>
<ProjectReference Include="..\MyWpfApp\MyWpfApp.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetPlatformVersion>10.0.22621.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<DefaultLanguage>en-US</DefaultLanguage>
<AppxPackageDir>$(SolutionDir)AppPackages\</AppxPackageDir>
</PropertyGroup>
Package.appxmanifest
マニフェストでは、ID、機能、ビジュアルアセットを定義します。
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity Name="MyCompany.MyApp"
Publisher="CN=My Company, O=My Company, L=Seattle, S=WA, C=US"
Version="1.0.0.0"
ProcessorArchitecture="x64" />
<Properties>
<DisplayName>My App</DisplayName>
<PublisherDisplayName>My Company</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop"
MinVersion="10.0.19041.0"
MaxVersionTested="10.0.22621.0" />
</Dependencies>
<Resources>
<Resource Language="en-us" />
</Resources>
<Applications>
<Application Id="App"
Executable="MyApp.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements DisplayName="My App"
Description="My application description"
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
証明書による署名
Windows にインストールするには、すべての MSIX パッケージに署名が必要です。署名証明書の Subject は、パッケージマニフェストの Publisher 属性と一致している必要があります。
自己署名証明書(開発用)
# Create a self-signed certificate for development
$cert = New-SelfSignedCertificate `
-Type Custom `
-Subject "CN=My Company, O=My Company, L=Seattle, S=WA, C=US" `
-KeyUsage DigitalSignature `
-FriendlyName "MyApp Dev Signing" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", `
"2.5.29.19={text}")
# Export PFX for CI usage
$password = ConvertTo-SecureString -String "$env:CERT_PASSWORD" -Force -AsPlainText
Export-PfxCertificate -Cert $cert `
-FilePath "MyApp_DevSigning.pfx" `
-Password $password
# Find signtool.exe dynamically (SDK version varies by machine)
$signtool = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" |
Sort-Object { [version]($_.Directory.Parent.Name) } -Descending |
Select-Object -First 1 -ExpandProperty FullName
# Sign the MSIX package
& $signtool sign /fd SHA256 /a /f "MyApp_DevSigning.pfx" `
/p "$env:CERT_PASSWORD" `
"AppPackages\MyApp_1.0.0.0_x64.msix"
信頼された CA の証明書(本番用)
Microsoft Store 以外で本番配布する場合:
- 信頼された CA(DigiCert、Sectigo、GlobalSign)からコード署名証明書を取得します
- Subject が
Package.appxmanifestのPublisherと一致している必要があります - 長期的な有効性を確保するため、署名にタイムスタンプを付与します
# Sign with a trusted CA certificate (from certificate store)
& signtool.exe sign /fd SHA256 /sha1 "THUMBPRINT_HERE" `
/tr http://timestamp.digicert.com /td SHA256 `
"AppPackages\MyApp_1.0.0.0_x64.msix"
# Sign with a PFX file
& signtool.exe sign /fd SHA256 /f "production-cert.pfx" `
/p "$env:CERT_PASSWORD" `
/tr http://timestamp.digicert.com /td SHA256 `
"AppPackages\MyApp_1.0.0.0_x64.msix"
Microsoft Store による署名
Microsoft Store に提出されたアプリは、取り込み処理中に Microsoft によって再署名されます。開発用署名証明書は、Microsoft が発行した証明書に置き換えられます。Store のみで配布する場合、本番用署名証明書は必要ありません。
<PropertyGroup>
<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
<PackageCertificateThumbprint>AUTO_GENERATED_BY_VS</PackageCertificateThumbprint>
</PropertyGroup>
証明書要件の概要
| 配布方法 | 証明書の種類 | 信頼された CA が必要 |
|---|---|---|
| 開発/テスト | 自己署名 | いいえ(証明書を手動でインストール) |
| エンタープライズのサイドロード | 自己署名または内部 CA | いいえ(グループポリシーで証明書を展開) |
| 直接ダウンロード | 信頼された CA(DigiCert など) | はい |
| Microsoft Store | テスト証明書(MS による再署名) | いいえ |
配布チャネル
Microsoft Store への提出
- Partner Center(https://partner.microsoft.com/dashboard)で Windows 開発者として登録します
- アプリ名を確保するため、アプリの予約を作成します
- Store との関連付けを行って MSIX パッケージをビルドします:
# Build for Store submission (creates .msixupload)
dotnet publish --configuration Release --runtime win-x64 \
/p:GenerateAppxPackageOnBuild=true \
/p:UapAppxPackageBuildMode=StoreUpload \
/p:AppxBundle=Auto
.msixuploadファイルを Partner Center から提出します- Microsoft がアプリを検証、署名し、公開します
App Installer によるサイドロード
App Installer(.appinstaller)を使用すると、自動更新に対応した直接配布が可能です。ファイルを Web サーバー、ネットワーク共有、または CDN でホストします。
<?xml version="1.0" encoding="utf-8"?>
<AppInstaller Uri="https://mycompany.com/apps/MyApp.appinstaller"
Version="1.0.0.0"
xmlns="http://schemas.microsoft.com/appx/appinstaller/2021">
<MainPackage Name="MyCompany.MyApp"
Version="1.0.0.0"
Publisher="CN=My Company, O=My Company, L=Seattle, S=WA, C=US"
ProcessorArchitecture="x64"
Uri="https://mycompany.com/apps/MyApp_1.0.0.0_x64.msix" />
<UpdateSettings>
<OnLaunch HoursBetweenUpdateChecks="12"
ShowPrompt="true"
UpdateBlocksActivation="false" />
<AutomaticBackgroundTask />
<ForceUpdateFromAnyVersion>false</ForceUpdateFromAnyVersion>
</UpdateSettings>
</AppInstaller>
ユーザーは次の方法でインストールします:
ms-appinstaller:?source=https://mycompany.com/apps/MyApp.appinstaller
エンタープライズ展開
管理対象のエンタープライズ環境では、次の方法を使用できます:
| 方法 | ツール | 最適な用途 |
|---|---|---|
| Microsoft Intune | Intune ポータル | クラウド管理デバイス |
| SCCM/MECM | Configuration Manager | オンプレミス管理デバイス |
| グループポリシー | DISM / PowerShell | ドメイン参加デバイス |
| PowerShell | Add-AppxPackage | スクリプトによる展開 |
# Enterprise deployment via PowerShell
Add-AppxPackage -Path "\\fileserver\apps\MyApp_1.0.0.0_x64.msix"
# Install for all users (requires admin)
Add-AppxProvisionedPackage -Online `
-PackagePath "MyApp_1.0.0.0_x64.msix" `
-SkipLicense
自動更新の構成
App Installer の自動更新(Windows 10 1709+)
App Installer の XML ファイルで、自動更新の動作を制御します:
<UpdateSettings>
<OnLaunch HoursBetweenUpdateChecks="12"
ShowPrompt="true"
UpdateBlocksActivation="false" />
<AutomaticBackgroundTask />
<ForceUpdateFromAnyVersion>false</ForceUpdateFromAnyVersion>
</UpdateSettings>
| 設定 | 説明 |
|---|---|
HoursBetweenUpdateChecks | 更新チェックの最小間隔(時間)(0 = 起動のたび) |
ShowPrompt | 更新前にユーザーに更新ダイアログを表示する |
UpdateBlocksActivation | 更新が完了するまでアプリの起動をブロックする |
AutomaticBackgroundTask | アプリを起動せずにバックグラウンドで更新を確認する |
ForceUpdateFromAnyVersion | 任意のバージョンからの更新を許可する(ダウングレードを含む) |
プログラムによる更新チェック(Windows App SDK)
カスタムの更新 UI やロジックが必要なアプリでは、Package.Current.CheckUpdateAvailabilityAsync() を使用します:
using Windows.ApplicationModel;
public class AppUpdateService
{
public async Task<bool> CheckForUpdatesAsync()
{
var result = await Package.Current.CheckUpdateAvailabilityAsync();
return result.Availability == PackageUpdateAvailability.Available
|| result.Availability == PackageUpdateAvailability.Required;
}
}
差分更新
MSIX は差分更新に対応しており、変更されたブロックのみがダウンロードされます。次の条件を満たす場合、自動的に適用されます:
- 同じ
PackageNameとPublisherを使用している Versionが更新されている- 古いパッケージと新しいパッケージが同じサーバーでホストされている
差分更新に追加の構成は必要ありません。
MSIX バンドル形式
MSIX バンドル(.msixbundle)は、複数のアーキテクチャ固有の MSIX パッケージを単一のダウンロード可能な成果物にまとめます。Windows は適切なアーキテクチャを自動的にインストールします。
バンドルの作成
# Build for multiple architectures
dotnet publish -c Release -r win-x64 /p:GenerateAppxPackageOnBuild=true
dotnet publish -c Release -r win-arm64 /p:GenerateAppxPackageOnBuild=true
# Find MakeAppx.exe dynamically (SDK version varies by machine)
$makeappx = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\MakeAppx.exe" |
Sort-Object { [version]($_.Directory.Parent.Name) } -Descending |
Select-Object -First 1 -ExpandProperty FullName
# Create bundle
& $makeappx bundle /d "AppPackages" /p "MyApp_1.0.0.0.msixbundle"
MSBuild によるバンドル生成
<PropertyGroup>
<AppxBundle>Always</AppxBundle>
<AppxBundlePlatforms>x64|arm64</AppxBundlePlatforms>
</PropertyGroup>
バンドルのレイアウト
MyApp_1.0.0.0.msixbundle
MyApp_1.0.0.0_x64.msix
MyApp_1.0.0.0_arm64.msix
CI/CD の MSIX ビルド手順
GitHub Actions の MSIX ビルド
# MSIX-specific build steps (embed in your CI workflow)
# For pipeline structure, see [skill:dotnet-gha-patterns]
jobs:
build-msix:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Decode signing certificate
run: |
$pfxBytes = [System.Convert]::FromBase64String("${{ secrets.SIGNING_CERT_BASE64 }}")
[System.IO.File]::WriteAllBytes("signing-cert.pfx", $pfxBytes)
shell: pwsh
- name: Build MSIX package
run: |
dotnet publish --configuration Release --runtime win-x64 `
/p:GenerateAppxPackageOnBuild=true `
/p:AppxPackageSigningEnabled=true `
/p:PackageCertificateKeyFile="${{ github.workspace }}\signing-cert.pfx" `
/p:PackageCertificatePassword="${{ secrets.CERT_PASSWORD }}"
shell: pwsh
- name: Upload MSIX artifact
uses: actions/upload-artifact@v4
with:
name: msix-package
path: AppPackages/**/*.msix
- name: Clean up certificate
if: always()
run: Remove-Item -Path "signing-cert.pfx" -ErrorAction SilentlyContinue
shell: pwsh
Azure DevOps の MSIX ビルド
# MSIX-specific build steps (embed in your ADO pipeline)
# For pipeline structure, see [skill:dotnet-ado-patterns]
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.0.x'
- task: DownloadSecureFile@1
name: signingCert
inputs:
secureFile: 'signing-cert.pfx'
- task: DotNetCoreCLI@2
displayName: 'Build MSIX'
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/MyApp.csproj'
arguments: >-
--configuration Release
--runtime win-x64
/p:GenerateAppxPackageOnBuild=true
/p:AppxPackageSigningEnabled=true
/p:PackageCertificateKeyFile=$(signingCert.secureFilePath)
/p:PackageCertificatePassword=$(CERT_PASSWORD)
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'AppPackages'
artifactName: 'msix-package'
AOT + MSIX
MSIX パッケージには、起動の高速化とランタイムのフットプリント縮小を実現する AOT コンパイル済みバイナリを含めることができます。PublishAot と MSIX パッケージ化を組み合わせます:
<PropertyGroup>
<PublishAot>true</PublishAot>
<WindowsPackageType>MSIX</WindowsPackageType>
</PropertyGroup>
AOT の MSBuild 構成の詳細(ILLink ディスクリプター、トリミングオプション、プラットフォームに関する考慮事項)については、[skill:dotnet-native-aot] を参照してください。
Windows SDK のバージョン要件
| 機能 | 最小 Windows バージョン | ビルド番号 |
|---|---|---|
| Windows App SDK での MSIX | Windows 10 | ビルド 19041(2004) |
| App Installer プロトコル | Windows 10 | ビルド 1709(Fall Creators Update) |
| 自動更新(OnLaunch) | Windows 10 | ビルド 1709 |
| バックグラウンド自動更新 | Windows 10 | ビルド 1803(April 2018 Update) |
| ForceUpdateFromAnyVersion | Windows 10 | ビルド 1809 |
| MSIX バンドル形式 | Windows 10 | ビルド 1709 |
| オプションパッケージ | Windows 10 | ビルド 1709 |
| 変更パッケージ | Windows 10 | ビルド 1809 |
| App Installer ファイルのホスティング | Windows 10 | ビルド 1709 |
| Microsoft Store への提出 | Windows App SDK 1.6+ | N/A |
ターゲットプラットフォームのバージョン設定
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformVersion>10.0.22621.0</TargetPlatformVersion>
</PropertyGroup>
エージェントが注意すべき点
-
マニフェストの
Publisherは署名証明書の Subject と完全に一致している必要があります -- 不一致の場合、ビルド時または署名時にSignTool Error: SignerSign() failedが発生します。 -
自己署名証明書は手動で信頼済みにする必要があります -- MSIX をインストールする前に、ユーザーは証明書を
Trusted PeopleまたはTrusted Root Certification Authoritiesにインストールする必要があります。 -
PFX ファイルや証明書のパスワードをソース管理にコミットしないでください -- 証明書は CI シークレット(GitHub Secrets、Azure DevOps Secure Files)として保存し、ビルドパイプライン中にデコードしてください。
-
AppxBundle=Autoでバンドルが生成されるのは、複数のアーキテクチャをビルドする場合のみです -- 単一アーキテクチャのビルドでは、バンドルではなくフラットな.msixファイルが生成されます。 -
MSIX アプリはコンテナーのようなサンドボックス内で動作します -- ファイルシステムへのアクセスは仮想化されます。
AppDataに書き込むアプリでは、パッケージ固有の場所にリダイレクトされます。ハードコードされたパスではなく、ApplicationData.CurrentAPI を使用してください。 -
ストアへの提出には
.msixではなく.msixuploadを使用します -- 正しいアップロード形式を生成するには、/p:UapAppxPackageBuildMode=StoreUploadを設定してください。 -
windows-latestでの CI ビルドには Windows SDK が含まれています --signtool.exeとMakeAppx.exeのために、別途 SDK をインストールする必要はありません。 -
CI の例では TFM のパスをハードコードしないでください -- 例が .NET の各バージョンで動作するよう、変数参照(例:
${{ github.workspace }})を使用してください。