Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa guida illustra come usare l'interfaccia della riga di comando di winapp con un'applicazione Flutter per aggiungere l'identità del pacchetto e creare un pacchetto dell'app come MSIX.
L'identità del pacchetto è un concetto di base nel modello di Windows app. Consente all'applicazione di access API Windows specifiche (ad esempio Notifiche, Sicurezza, API di intelligenza artificiale e così via), avere un'esperienza di installazione/disinstallazione pulita e altro ancora.
Prerequisiti
Flutter SDK: installare Flutter seguendo la guida ufficiale.
CLI winapp: installare il
winappCLI tramite winget:winget install Microsoft.winappcli --source winget
1. Creare una nuova app Flutter
Seguire la guida alla documentazione ufficiale di Flutter per creare una nuova applicazione ed eseguirla.
2. Aggiornare il codice per verificare l'identità
Aggiungere il pacchetto ffi:
flutter pub add ffi
Sostituire il contenuto di lib/main.dart con il codice seguente che verifica l'identità del pacchetto usando l'API Windows GetCurrentPackageFamilyName tramite Dart FFI:
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:ffi/ffi.dart';
import 'package:flutter/material.dart';
String? getPackageFamilyName() {
if (!Platform.isWindows) return null;
final kernel32 = DynamicLibrary.open('kernel32.dll');
final getCurrentPackageFamilyName = kernel32.lookupFunction<
Int32 Function(Pointer<Uint32>, Pointer<Uint16>),
int Function(
Pointer<Uint32>, Pointer<Uint16>)>('GetCurrentPackageFamilyName');
final length = calloc<Uint32>();
try {
final result =
getCurrentPackageFamilyName(length, Pointer<Uint16>.fromAddress(0));
if (result != 122) return null; // ERROR_INSUFFICIENT_BUFFER = 122
final namePtr = calloc<Uint16>(length.value);
try {
final result2 = getCurrentPackageFamilyName(length, namePtr);
if (result2 == 0) {
return namePtr.cast<Utf16>().toDartString();
}
return null;
} finally {
calloc.free(namePtr);
}
} finally {
calloc.free(length);
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
late final String? _packageFamilyName;
@override
void initState() {
super.initState();
_packageFamilyName = getPackageFamilyName();
}
void _incrementCounter() {
setState(() { _counter++; });
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(bottom: 24),
decoration: BoxDecoration(
color: _packageFamilyName != null
? Colors.green.shade50
: Colors.orange.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: _packageFamilyName != null
? Colors.green
: Colors.orange,
),
),
child: Text(
_packageFamilyName != null
? 'Package Family Name:\n$_packageFamilyName'
: 'Not packaged',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge,
),
),
const Text('You have pushed the button this many times:'),
Text('$_counter',
style: Theme.of(context).textTheme.headlineMedium),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
3. Eseguire senza identità
Compilare ed eseguire l'app:
flutter build windows
.\build\windows\x64\runner\Release\flutter_app.exe
Dovrebbe essere visualizzata l'app con un indicatore arancione "Non incluso nel pacchetto".
4. Inizializzare il progetto con la CLI di winapp
winapp init
Quando richiesto:
- Nome pacchetto: premere INVIO per accettare l'impostazione predefinita
- Publisher nome: premere INVIO per accettare il valore predefinito o immettere il nome
- Versione: premere INVIO per accettare 1.0.0.0
- Punto di ingresso: premere INVIO per accettare il valore predefinito (flutter_app.exe)
- Setup SDKs: Selezionare "SDK Stabili" per scaricare Windows App SDK e generare intestazioni C++
5. Eseguire il debug con l'identità
Compilare l'app:
flutter build windowsApplicare l'identità di debug:
winapp create-debug-identity .\build\windows\x64\runner\Release\flutter_app.exeEseguire il file eseguibile:
.\build\windows\x64\runner\Release\flutter_app.exe
Verrà visualizzata l'app con un indicatore verde che mostra il nome della famiglia di pacchetti.
Annotazioni
Dopo l'esecuzione flutter clean o la ricompilazione, è necessario eseguire nuovamente l'esecuzione create-debug-identity perché l'eseguibile viene sostituito.
6. Pacchetto con MSIX
Compilazione per il rilascio:
flutter build windowsPreparare la directory del pacchetto:
mkdir dist copy .\build\windows\x64\runner\Release\* .\dist\ -RecurseGenerare un certificato di sviluppo:
winapp cert generate --if-exists skipPacchetto e firma:
winapp pack .\dist --cert .\devcert.pfxInstallare il certificato (esegui come amministratore):
winapp cert install .\devcert.pfxInstallare il pacchetto:
Add-AppxPackage .\flutter-app.msix
Suggerimento
- Microsoft Store firma MSIX per te, non è necessario firmare prima dell'invio.
- Azure Trusted Signing è un ottimo modo per gestire i certificati in modo sicuro per le pipeline CI/CD.