Korzystanie z winapp CLI z platformą .NET

Ten przewodnik powinien działać w przypadku większości typów projektów .NET. Kroki zostały przetestowane w projektach konsolowych oraz projektach typu WPF opartych na interfejsie użytkownika. Aby zapoznać się z przykładami pracy, zapoznaj się z przykładami dotnet-app (konsola) i wpf-app (WPF) w folderze samples.

W tym przewodniku pokazano, jak używać interfejsu wiersza polecenia (CLI) winapp z aplikacją .NET do debugowania z wykorzystaniem tożsamości pakietu oraz zapakowania aplikacji w postaci pliku MSIX.

Tożsamość pakietu jest podstawową koncepcją w modelu Windows app. Umożliwia Twojej aplikacji dostęp do specyficznych interfejsów API Windows (takich jak powiadomienia, zabezpieczenia, interfejsy API sztucznej inteligencji itp.), zapewnia czyste środowisko instalacji i dezinstalacji oraz oferuje wiele innych funkcji.

Standardowy plik wykonywalny (taki jak utworzony za pomocą dotnet buildpolecenia ) nie ma tożsamości pakietu. W tym przewodniku pokazano, jak dodać go do debugowania, a następnie spakować go do dystrybucji.

Wymagania wstępne

  1. .NET SDK: Zainstaluj zestaw SDK .NET (wymaga ponownego uruchomienia po instalacji):

    winget install Microsoft.DotNet.SDK.10 --source winget
    
  2. winapp CLI: Zainstaluj narzędzie winapp za pomocą pakietu winget (lub zaktualizuj, jeśli już zainstalowane):

    winget install Microsoft.winappcli --source winget
    

1. Tworzenie nowej aplikacji .NET

Zacznij od utworzenia prostej aplikacji konsolowej .NET:

dotnet new console -n dotnet-app
cd dotnet-app

Uruchom go, aby upewnić się, że wszystko działa:

dotnet run

Dane wyjściowe powinny mieć wartość "Hello, World!"

2. Zaktualizuj kod, aby sprawdzić tożsamość

Zaktualizujemy aplikację, aby sprawdzić, czy jest ona uruchomiona przy użyciu tożsamości pakietu. Użyjemy interfejsu API środowisko wykonawcze systemu Windows, aby uzyskać dostęp do API pakietów.

Najpierw zaktualizuj plik project, aby był przeznaczony dla określonej wersji zestawu Windows SDK. Otwórz dotnet-app.csproj i zmień TargetFramework, aby uwzględnić wersję zestawu SDK Windows:

  <TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>

Zapewnia to dostęp do interfejsów API środowisko wykonawcze systemu Windows bez konieczności używania dodatkowych pakietów.

Teraz zastąp zawartość Program.cs pliku poniższym kodem. Ten kod próbuje pobrać bieżącą tożsamość pakietu przy użyciu interfejsu API środowisko wykonawcze systemu Windows. Jeśli to się powiedzie, wyświetla nazwę rodziny pakietów; w przeciwnym razie wyświetla tekst "Nie spakowane".

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. Uruchamianie bez tożsamości

Teraz uruchom aplikację w zwykły sposób:

dotnet run

Powinny zostać wyświetlone dane wyjściowe "Nie spakowane". Potwierdza to, że standardowy plik wykonywalny jest uruchomiony bez żadnej tożsamości pakietu.

4. Inicjowanie Projektu za pomocą CLI winapp

Polecenie winapp init automatycznie wykrywa pliki .csproj i uruchamia konfigurację specyficzną dla .NET. Konfiguruje wszystko, czego potrzebujesz w jednym miejscu: weryfikuje element TargetFramework, dodaje wymagane pakiety NuGet, generuje manifest aplikacji i zasoby.

Uruchom następujące polecenie i postępuj zgodnie z monitami:

winapp init

Po wyświetleniu monitu:

  • Nazwa pakietu: naciśnij klawisz Enter, aby zaakceptować wartość domyślną (dotnet-app)
  • Nazwa wydawcy: Naciśnij klawisz Enter, aby zaakceptować wartość domyślną lub wprowadź swoją nazwę
  • Wersja: Naciśnij klawisz Enter, aby zaakceptować 1.0.0.0
  • Description: Naciśnij klawisz Enter, aby zaakceptować wartość domyślną (Windows Aplikacja) lub wprowadź opis
  • Zestaw SDK do aplikacji systemu Windows setup: Select Stable, Preview lub Experimental (określa, która wersja Zestaw SDK do aplikacji systemu Windows jest dodawana)
  • TargetFramework update: Jeśli TargetFramework nie zawiera obsługiwanej wersji zestawu SDK Windows, zostanie wyświetlony monit o zaktualizowanie go (np. net10.0-windows10.0.26100.0)
  • Tryb dewelopera: jeśli zostanie wyświetlony monit o "Tryb dewelopera", możesz włączyć go, jeśli chcesz, ale pamiętaj, że wymaga uprawnień administracyjnych

To polecenie spowoduje:

  • Zaktualizuj TargetFramework w .csproj do TFM obsługiwanego przez Windows (w razie potrzeby)
  • Dodaj Microsoft.WindowsAppSDK, Microsoft.Windows.SDK.BuildTools i Microsoft.Windows.SDK.BuildTools.WinApp odwołania do pakietu NuGet do .csproj
  • Utwórz folder Package.appxmanifest i Assets dla tożsamości aplikacji

Uwaga / Notatka

W przeciwieństwie do projektów natywnych/C++ przepływ .NET nie tworzy pliku . Pakiety NuGet są zarządzane bezpośrednio za pośrednictwem elementu .csproj. Po sklonowaniu uruchom polecenie winapp restore lub dotnet restore.

Możesz otworzyć Package.appxmanifest aby jeszcze bardziej dostosować właściwości, takie jak nazwa wyświetlana, wydawca i funkcje.

Aby sprawdzić, czy pakiety zostały dodane do projektu:

dotnet list package

W danych wyjściowych powinny zostać wyświetlone Microsoft.WindowsAppSDK i Microsoft.Windows.SDK.BuildTools.

Dane wyjściowe konsoli (nic do zrobienia)

Ponieważ tworzysz aplikację konsolową, dane wyjściowe konsoli muszą pozostać w bieżącym terminalu. Aktywacja AUMID powoduje, że spakietowana aplikacja nie ma konsoli, więc aplikacja konsolowa będzie działać poprawnie, ale nic nie wyświetli.

Aplikacja winapp obsługuje to dla Ciebie: aplikacja z OutputType=Exe programem jest uruchamiana za pośrednictwem aliasu wykonywania, który dziedziczy stdin/stdout/stderr terminalu. Dodaje wymagane uap5:ExecutionAlias do przygotowywanego manifestu, więc nie trzeba nic konfigurować.

Aplikacje interfejsu użytkownika (WPF, WinForms, WinUI) renderują własne okno, dzięki czemu zachowują aktywację AUMID.

Aby mimo to wymusić identyfikator AUMID dla aplikacji konsolowej, ustaw poniższy wpis wewnątrz dowolnego <PropertyGroup> w dotnet-app.csproj — aplikacja będzie wtedy uruchamiana bez konsoli i nie będzie nic wyświetlać w terminalu:

<WinAppRunUseExecutionAlias>false</WinAppRunUseExecutionAlias>

Jeśli wolisz samodzielnie wybrać nazwę polecenia, uruchom winapp manifest add-alias, aby zadeklarować ją w pliku Package.appxmanifest; alias utworzony przez Ciebie zostanie użyty bez zmian.

5. Debugowanie przy użyciu tożsamości

Ponieważ winapp init dodał pakiet Microsoft.Windows.SDK.BuildTools.WinApp NuGet do projektu, możesz po prostu uruchomić:

dotnet run

Spowoduje to automatyczne wywołanie winapp run pod maską — utworzenie luźnego pakietu układu, zarejestrowanie go w Windows i uruchomienie aplikacji z pełną tożsamością pakietu.

Argumenty wpisane po dotnet run trafiają do Twojej aplikacji dokładnie tak, jakby projekt nie odwoływał się do tego pakietu:

dotnet run --devtools          # your app receives --devtools
dotnet run -- --devtools       # identical: the SDK consumes the -- before forwarding

Użyj --, gdy flaga w aplikacji jest również opcją dotnet run (--configuration, --framework, -c, --project, -f, -r, ...) — bez tego token zostaje przechwycony przez SDK, a aplikacja nigdy go nie otrzymuje:

dotnet run -- --configuration Release   # your app receives --configuration Release

Skonfiguruj aplikację WinApp launcher przy użyciu WinAppRun* właściwości MSBuild. Program MSBuild korzysta z tych elementów, więc nigdy nie docierają do aplikacji:

dotnet run -p:WinAppRunDebugOutput=true --devtools

Tutaj właściwość konfiguruje aplikację WinApp, a --devtools jest przekazywany do Twojej aplikacji. Zobacz dotnet run pomoc techniczną, aby wyświetlić pełną listę właściwości, w tym właściwości, których nie można łączyć.

Uwaga / Notatka

Mogą pojawić się ostrzeżenia dotyczące luk w zabezpieczeniach NuGet (NU1900) dotyczące źródeł pakietów. Bez obaw można je zignorować — nie wpływają na kompilację.

Powinny zostać wyświetlone dane wyjściowe podobne do następujących:

Package Family Name: dotnet-app_12345abcde

Potwierdza to, że aplikacja jest uruchomiona z prawidłową tożsamością pakietu!

Alternatywa: Ręczne winapp run

Jeśli nie użyto winapp init (lub usunięto pakiet NuGet), możesz skompilować i uruchomić ręcznie. winapp run akceptuje projekt bezpośrednio (tryb projektu) — kompiluje .csproj i uruchamia go, więc nie musisz wskazywać na folder build-output ani kompilować oddzielnie:

# Build and run the project in one step (project mode)
winapp run .

# ...or run a specific project / configuration / architecture
winapp run .\dotnet-app.csproj -c Debug --arch x64

Aby uruchomić natywną konfigurację AOT projektu, włącz funkcję AOT w projekcie i uruchom polecenie:

winapp run . --aot
winapp run . --aot -c Release

Użyj architektury x64 lub ARM64. W przypadku jednorazowego zastąpienia dołącz element -p PublishAot=true.

Jeśli wolisz, nadal możesz wskazać w winapp run wcześniej utworzony folder wyjściowy (tryb folderu):

dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0

Tryb projektu obsługuje zarówno pakietowane, jak i niepakietowane aplikacje WinUI — wykrywa ich typ na podstawie elementu WindowsPackageType projektu i automatycznie instaluje środowisko aplikacja dla systemu Windows Runtime w zgodnej architekturze. Aby wymusić uruchomienie projektu spakietowanego w trybie bez pakietu, dodaj przełącznik -p WindowsPackageType=None.

Aplikacje wieloprojektowe (aplikacje odwołujące się do bibliotek klas) kompilują się prawidłowo: winapp zachowuje odwołania AnyCPU/netstandard2.0 na zgodnej platformie docelowej, zamiast wymuszać architekturę aplikacji w całym grafie zależności. Tryb tylko RID pozostaje ustawieniem domyślnym; gdy efektywna konfiguracja wymaga profilu self-contained (na przykład przy przyciętej kompilacji w konfiguracji Release), winapp wybiera pasujący profil bez zmiany platform docelowych bibliotek, do których istnieją odwołania.

Strumienie wyjściowe dotnet build są przesyłane na żywo, przy czym najpierw wyświetlane jest dokładne wywołanie. Dodaj --verbose dla śladów decyzji kompilacji własnych aplikacji winapp. Wymaga zestawu SDK .NET w wersji 8.0.100 lub nowszej. Zobacz winapp run w dokumentacji użycia , aby uzyskać pełną listę opcji.

Nie zainstalowano zestawu SDK Windows? Projekty tworzenia C#/WinRT zwykle wymagają zarejestrowanego zestawu SDK Windows do skompilowania. Gdy tryb projektu nie wykryje żadnych z nich (czyste środowisko CI, kontenery, środowiska deweloperskie bez SDK), wskazuje narzędziu cswinrt pliki winmd z pakietu Microsoft.Windows.SDK.NET.Ref, który został automatycznie przywrócony, dzięki czemu kompilacja nadal się powiedzie — nie trzeba nic robić. Nie powoduje to żadnych zmian, gdy zainstalowany jest zestaw SDK lub gdy samodzielnie ustawisz -p CsWinRTWindowsMetadata=….

Aby ponownie dodać pakiet NuGet: dotnet add package Microsoft.Windows.SDK.BuildTools.WinApp --prerelease

Wskazówka

Aby wyłączyć automatyczną dotnet run integrację, dodaj <EnableWinAppRunSupport>false</EnableWinAppRunSupport> do .csproj. Aby uzyskać opcje dostosowywania, zobacz dotnet run support docs (Dokumentacja dotycząca obsługi uruchamiania dotnet ).

Alternatywna: tożsamość pakietu rozrzednego

Jeśli potrzebujesz rzadkiego zachowania pakietów (identyczność bez kopiowania plików), możesz użyć zamiast tego create-debug-identity. Spowoduje to zarejestrowanie rzadkiego pakietu wskazującego na plik exe zamiast tworzenia luźnego rozmieszczenia.

winapp create-debug-identity .\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe

Następnie uruchom plik wykonywalny bezpośrednio (nie używaj dotnet run, ponieważ może on ponownie skompilować lub zastąpić plik):

.\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe

Alternatywa: Ręczny cel MSBuild

Jeśli nie chcesz używać pakietu NuGet, możesz dodać niestandardowy element docelowy programu MSBuild uruchamiany create-debug-identity po kompilacjach debugowania. Dodaj to do pliku .csproj na końcu, tuż przed zamykającym tagiem </Project>:

  <!-- Automatically apply debug identity after Debug builds -->
  <Target Name="ApplyDebugIdentity" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
    <Exec Command="winapp create-debug-identity &quot;$(TargetDir)$(TargetName).exe&quot;" 
          WorkingDirectory="$(ProjectDir)" 
          IgnoreExitCode="false" />
  </Target>

W przypadku tej konfiguracji dotnet build stosuje identyfikator debugowania i umożliwia bezpośrednie uruchomienie pliku wykonywalnego. Pamiętaj, że dotnet run może to spowodować ponowne skompilowanie i zastąpienie tożsamości, dlatego uruchom plik exe ręcznie po utworzeniu.

Wskazówka

Aby uzyskać zaawansowane scenariusze debugowania (dołączanie debugerów, konfigurowanie środowiska IDE, debugowanie uruchamiania), zobacz Przewodnik debugowania.

Kiedy pominąć to: Jeśli wolisz jawną kontrolę nad zastosowaniem tożsamości lub jeśli pracujesz nad kodem, który nie potrzebuje tożsamości w większości cyklu programowania, powyższe podejście ręczne może być prostsze.

6. Używanie Zestaw SDK do aplikacji systemu Windows (opcjonalnie)

Zestaw SDK do aplikacji systemu Windows zapewnia dostęp do nowoczesnych interfejsów API Windows poza podstawowym zestawem SDK Windows — takich jak system powiadomień, interfejsy API okien, zarządzanie cyklem życia aplikacji i sztuczna inteligencja na urządzeniu. Jeśli Twoja aplikacja potrzebuje dowolnej z tych możliwości, ten krok jest dla Ciebie. Jeśli potrzebujesz tożsamości pakietu do dystrybucji, możesz przejść do kroku 7.

Jeśli uruchomiłeś winapp init (krok 4), Microsoft.WindowsAppSDK został już dodany jako odwołanie pakietu NuGet do .csproj. Możesz zweryfikować za pomocą polecenia dotnet list package. Jeśli podczas inicjowania pominięto konfigurację zestawu SDK lub musisz dodać ją ręcznie, uruchom polecenie:

dotnet add package Microsoft.WindowsAppSDK

Zaktualizuj Program.cs

Zastąp całą zawartość Program.cs następującym kodem, który dodaje sprawdzanie wersji środowiska uruchomieniowego aplikacja dla systemu 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");
        }
    }
}

Budowanie i uruchamianie

Skompiluj i uruchom aplikację przy użyciu Zestaw SDK do aplikacji systemu Windows. Ponieważ dodaliśmy zestaw WinAppSDK, musimy ponownie zarejestrować się przy użyciu tożsamości, aby winapp dodać zależność środowiska uruchomieniowego. Jeśli dodano pakiet NuGet WinApp (zalecane), po prostu uruchom dotnet run. W przeciwnym razie (zastąp dotnet-app nazwą projektu):

dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0

Powinny zostać wyświetlone dane wyjściowe, takie jak:

Package Family Name: dotnet-app.debug_12345abcde
Windows App Runtime Version: 8000.770.947.0

Pakiet Zestaw SDK do aplikacji systemu Windows NuGet zawiera wszystkie zestawy niezbędne do uzyskiwania dostępu do nowoczesnych interfejsów API Windows, w tym:

  • Powiadomienia i dynamiczne kafelki
  • Cykl życia okien i aplikacji
  • Powiadomienia push
  • I wiele innych składników Zestaw SDK do aplikacji systemu Windows

Aby uzyskać bardziej zaawansowane użycie Zestaw SDK do aplikacji systemu Windows, zapoznaj się z dokumentacją Zestaw SDK do aplikacji systemu Windows.

7. Pakiet z plikiem MSIX

Gdy wszystko będzie gotowe do dystrybucji aplikacji, możesz spakować ją jako plik MSIX przy użyciu tego samego manifestu.

Kompilacja dla wydania

Najpierw skompiluj aplikację w trybie wydania, aby uzyskać optymalną wydajność:

dotnet build -c Release

Uwaga / Notatka

Mogą zostać wyświetlone ostrzeżenia dotyczące luk w zabezpieczeniach NuGet (NU1900). Są one bezpieczne do ignorowania i nie mają wpływu na dane wyjściowe kompilacji.

Generowanie certyfikatu programistycznego

Przed pakowaniem potrzebny jest certyfikat dewelopera do podpisywania. Wygeneruj go, jeśli jeszcze tego nie zrobiono:

winapp cert generate --if-exists skip

Podpisywanie i pakowanie

Teraz możesz spakować i podpisać. Skieruj polecenie pack do folderu wyjściowego kompilacji, zastępując dotnet-app i ścieżkę TFM wartościami projektu.

# 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 

Uwaga: polecenie pack automatycznie używa pliku Package.appxmanifest z bieżącego katalogu i kopiuje go do folderu docelowego przed opakowaniem. Wygenerowany plik msix będzie znajdować się w bieżącym katalogu.

Porada: Możesz również pominąć wyszukiwanie folderu build-output i spakować bezpośrednio z projektu — winapp package .\dotnet-app.csproj --cert .\devcert.pfx publikuje projekt i pakuje dane wyjściowe w jednym kroku (w trybie projektu domyślnie używana jest konfiguracja Release). Tryb projektu akceptuje opcje kompilacji -c, --arch, -f, --no-build, --no-restore, -p; dodaj --no-build, aby spakować istniejącą kompilację bez ponownej kompilacji.

Instalowanie certyfikatu

Przed zainstalowaniem pakietu MSIX należy zainstalować certyfikat dewelopera. Uruchom to polecenie jako administrator:

winapp cert install .\devcert.pfx

Instalowanie i uruchamianie

Zainstaluj pakiet, klikając dwukrotnie wygenerowany plik *.msix.

Teraz możesz uruchomić aplikację z dowolnego miejsca w terminalu, wpisując:

dotnet-app

Powinny zostać wyświetlone dane wyjściowe "Nazwa rodziny pakietów", potwierdzające, że pakiet został zainstalowany i działa z unikalnym identyfikatorem.

Wskazówka

Jeśli musisz ponownie spakować aplikację (np. po zmianie kodu), zwiększ Version wartość w Package.appxmanifest przed ponownym uruchomieniem winapp pack . Windows wymaga wyższego numeru wersji w celu zaktualizowania zainstalowanego pakietu.

Porady

  1. Gdy wszystko będzie gotowe do dystrybucji, możesz podpisać plik MSIX przy użyciu certyfikatu podpisywania kodu z urzędu certyfikacji, aby użytkownicy nie musieli instalować certyfikatu z podpisem własnym.
  2. Microsoft Store podpisze plik MSIX bez konieczności podpisywania przed przesłaniem.
  3. Może być konieczne utworzenie wielu pakietów MSIX — po jednym dla każdej obsługiwanej architektury (x64, Arm64). Użyj flagi -r z dotnet build , aby kierować do określonych architektur: dotnet build -c Release -r win-x64 lub dotnet build -c Release -r win-arm64.

Automatyzowanie pakowania MSIX (opcjonalnie)

Aby zautomatyzować pakowanie MSIX w ramach kompilacji wydawniczych, dodaj ten cel do pliku .csproj (możesz dodać go wraz z celem do debugowania).

  <!-- 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 &quot;$(TargetDir.TrimEnd('\'))&quot; --cert &quot;$(ProjectDir)devcert.pfx&quot;" 
          WorkingDirectory="$(ProjectDir)" 
          IgnoreExitCode="false" />
  </Target>

W tej konfiguracji:

  • Kompilowanie w trybie wydania (dotnet build -c Release) spowoduje automatyczne utworzenie pakietu MSIX
  • Plik MSIX jest spakowany i podpisany przy użyciu certyfikatu dewelopera
  • Plik ostateczny .msix znajdzie się w katalogu głównym projektu

Można również utworzyć konfigurację niestandardową (np. PackagedRelease), modyfikując warunek na '$(Configuration)' == 'PackagedRelease'.

Dalsze kroki