Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Deze handleiding laat zien hoe u een systeemeigen C#-invoegtoepassing maakt die gebruikmaakt van Windows Machine Learning (WinML) in uw Electron-app. Met WinML kunt u lokaal machine learning modellen (ONNX-indeling) uitvoeren op Windows-apparaten voor taken zoals afbeeldingsclassificatie, objectdetectie en meer.
Vereiste voorwaarden
Voordat u aan deze handleiding begint, moet u het volgende doen:
- De installatie van de ontwikkelomgeving is voltooid
- Windows 11 of Windows 10 (versie 1809 of hoger)
Opmerking
WinML wordt uitgevoerd op elk Windows 10 (1809+) of Windows 11 apparaat. Voor de beste prestaties worden apparaten met GPU's of NPU's aanbevolen, maar de API werkt ook op CPU.
Belangrijk
De WinML-invoegtoepassing vereist de experimental Windows App SDK. Als u 'Stabiele SDK's' hebt geselecteerd tijdens winapp init de installatiehandleiding, moet u de SDK-versie bijwerken. Bewerk winapp.yaml en wijzig de versie Microsoft.WindowsAppSDK in 2.0.0-experimental3 en voer vervolgens npx winapp restore uit om bij te werken.
Stap 1: Een systeemeigen C#-invoegtoepassing maken
Laten we een systeemeigen invoegtoepassing maken die Gebruikmaakt van WinML-API's. We gebruiken een C#-sjabloon die gebruikmaakt van node-api-dotnet om JavaScript en C# te overbrugmen.
npx winapp node create-addon --template cs --name winMlAddon
Hiermee maakt u een winMlAddon/ map met:
-
addon.cs- Uw C#-code die WinML-API's aanroept -
winMlAddon.csproj- Project bestand met verwijzingen naar Windows SDK en Windows App SDK -
README.md- Documentatie over het gebruik van de invoegtoepassing
Met de opdracht wordt ook een build-winMlAddon script aan uw package.json toegevoegd voor het bouwen van de invoegtoepassing en een clean-winMlAddon script voor het opschonen van buildartefacten:
{
"scripts": {
"build-winMlAddon": "dotnet publish ./winMlAddon/winMlAddon.csproj -c Release",
"clean-winMlAddon": "dotnet clean ./winMlAddon/winMlAddon.csproj"
}
}
De sjabloon bevat automatisch verwijzingen naar beide SDK's, zodat u onmiddellijk Windows API's kunt aanroepen.
Laten we controleren of alles correct is ingesteld door de invoegtoepassing te bouwen:
# Build the C# addon
npm run build-winMlAddon
Opmerking
U kunt ook een C++-invoegtoepassing maken met behulp van npx winapp node create-addon (zonder de --template vlag). C++ invoegtoepassingen gebruiken node-addon-api en bieden directe toegang tot Windows API's met maximale prestaties. Zie de handleiding voor de C++-meldingsinvoegtoepassing voor een overzicht of de volledige opdrachtdocumentatie voor meer opties.
Stap 2: Het SqueezeNet-model downloaden en voorbeeldcode ophalen
We gebruiken het Classificeer Afbeeldingen voorbeeld uit de AI Dev Gallery als referentie. In dit voorbeeld wordt het SqueezeNet 1.1-model gebruikt voor afbeeldingsclassificatie.
2.1. Het model downloaden
- De AI Dev Gallery installeren
- Navigeer naar het voorbeeld van de classificatieafbeelding
- Download het SqueezeNet 1.1-model (het ondersteunt CPU, GPU en NPU)
- Klik op Openen met map om het
.onnxbestand te zoeken
- Kopieer het bestand
squeezenet1.1.onnxnaar een mapmodels/in de hoofdmap van uw project
Opmerking
Het model kan ook rechtstreeks worden gedownload vanuit de ONNX Model Zoo GitHub opslagplaats
Stap 3: Vereiste NuGet-pakketten toevoegen
Voordat u de WinML-code toevoegt, moeten we extra NuGet-pakketten toevoegen die vereist zijn voor het verwerken van afbeeldingen, ONNX Runtime en GenAI-ondersteuning.
3.1. Directory.packages.props bijwerken
Voeg de volgende pakketversies toe aan het Directory.packages.props bestand in de hoofdmap van uw project (moet zijn gemaakt toen u de invoegtoepassing maakte):
<Project>
<PropertyGroup>
<!-- Enable central package versioning -->
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.JavaScript.NodeApi" Version="0.9.17" />
<PackageVersion Include="Microsoft.JavaScript.NodeApi.Generator" Version="0.9.17" />
<!-- Add these packages for WinML -->
+ <PackageVersion Include="Microsoft.ML.OnnxRuntime.Extensions" Version="0.14.0" />
+ <PackageVersion Include="System.Drawing.Common" Version="9.0.9" />
+ <PackageVersion Include="Microsoft.Extensions.AI" Version="9.9.1" />
+ <PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.Managed" Version="0.10.1" />
+ <PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.WinML" Version="0.10.1" />
<!-- These versions may be updated automatically during restore to match yaml -->
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.0.0-experimental3" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
</ItemGroup>
</Project>
3.2. WinMlAddon.csproj bijwerken
Open winMlAddon/winMlAddon.csproj en voeg de pakketverwijzingen toe aan het volgende <ItemGroup>:
<ItemGroup>
<PackageReference Include="Microsoft.JavaScript.NodeApi" />
<PackageReference Include="Microsoft.JavaScript.NodeApi.Generator" />
<!-- Add these packages for WinML -->
+ <PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions" />
+ <PackageReference Include="System.Drawing.Common" />
+ <PackageReference Include="Microsoft.Extensions.AI" />
+ <PackageReference Include="Microsoft.ML.OnnxRuntimeGenAI.Managed" />
+ <PackageReference Include="Microsoft.ML.OnnxRuntimeGenAI.WinML" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
</ItemGroup>
Wat deze pakketten doen:
- Microsoft.ML.OnnxRuntime.Extensions - biedt extra operators en hulpprogramma's voor ONNX Runtime
- System.Drawing.Common - Hiermee schakelt u het laden en bewerken van afbeeldingen in voorverwerking
- Microsoft. Extensions.AI - AI-abstracties voor .NET
- Microsoft.ML.OnnxRuntimeGenAI.Managed - Beheerde bindingen voor ONNX Runtime GenAI
- Microsoft.ML.OnnxRuntimeGenAI.WinML - WinML-integratie voor ONNX Runtime GenAI
Stap 4: De voorbeeldcode toevoegen
In de AI Dev Gallery ziet u de volledige implementatie voor afbeeldingsclassificatie met SqueezeNet:
We hebben deze code voor Electron aangepast en u kunt de volledige implementatie vinden in het elektron-winml-monster. De winMlAddon/ map bevat de gewijzigde code uit de AI Dev Gallery.
Kopieer de hele winMlAddon/ map uit samples/electron-winml/winMlAddon/ naar de hoofdmap van uw project, waarbij u de map vervangt die u in stap 1 hebt gemaakt. Het voorbeeld bevat meer dan meerdere bestanden addon.cs (helperklassen in Utils/, een chatclient, enzovoort) die nodig zijn om de invoegtoepassing te bouwen en uit te voeren.
Belangrijk
U moet de hele map kopiëren, niet alleen addon.cs. De invoegtoepassing is afhankelijk van helperbestanden in de Utils/ submap (Prediction.cs, ImageNet.csBitmapFunctions.cs, enzovoort).
Belangrijke implementatiedetails
Laten we de belangrijke onderdelen van de implementatie en de belangrijkste verschillen van de AI Dev Gallery-code markeren:
1. Projecthoofdpadvereiste
In tegenstelling tot de AI Dev Gallery-code vereist onze Electron-invoegtoepassing de JavaScript-code om het hoofdpad van het project door te geven. Dit is nodig omdat:
- De invoegtoepassing moet het ONNX-modelbestand in de
models/map zoeken - Systeemeigen afhankelijkheden (DLL's) moeten worden geladen vanuit specifieke mappen
[JSExport]
public static async Task<Addon> CreateAsync(string projectRoot)
{
if (!Path.Exists(projectRoot))
{
throw new Exception("Project root is invalid.");
}
var addon = new Addon(projectRoot);
addon.PreloadNativeDependencies();
string modelPath = Path.Join(projectRoot, "models", @"squeezenet1.1-7.onnx");
await addon.InitModel(modelPath, ExecutionProviderDevicePolicy.DEFAULT, null, false, null);
return addon;
}
Hiermee selecteert u automatisch de beste uitvoeringsprovider (CPU, GPU of NPU) op basis van de mogelijkheden van het apparaat.
2. Systeemeigen afhankelijkheden vooraf laden
De invoegtoepassing bevat een PreloadNativeDependencies() methode voor het laden van vereiste DLL's. Deze benadering werkt zowel voor ontwikkelings- als productiescenario's zonder DLL's naar de hoofdmap van het project te hoeven kopiëren:
private void PreloadNativeDependencies()
{
// Loads required DLLs from the winMlAddon build output
// This ensures dependencies are available regardless of the execution context
}
Dit wordt aangeroepen tijdens de initialisatie voordat het model wordt geladen, zodat alle systeemeigen bibliotheken beschikbaar zijn.
3. Electron Forge configureren voor het verpakken
Om ervoor te zorgen dat de invoegtoepassing correct werkt in productieversies, moet u uw packager configureren voor:
- Systeemeigen bestanden uitpakken - DLL's, ONNX-modellen en .node-bestanden moeten toegankelijk zijn buiten het ASAR-archief
- Onnodige bestanden uitsluiten - Houd de pakketgrootte klein door buildartefacten en tijdelijke bestanden uit te sluiten
Werk uw forge.config.js bij voor Electron Forge.
// From samples/electron-winml/forge.config.js
module.exports = {
packagerConfig: {
asar: {
// Unpack native files so they can be accessed by the addon
unpack: "**/*.{dll,exe,node,onnx}"
},
ignore: [
// Exclude .winapp folder (SDK packages and headers)
/^\/.winapp\//,
// Exclude MSIX packages
"\\.msix$",
// Exclude winMlAddon source files, but keep the dist folder
/^\/winMlAddon\/(?!dist).+/
]
},
// ... rest of your config
};
Wat dit doet:
asar.unpack- Extraheert DLL's, uitvoerbare bestanden, .node binaire bestanden en ONNX-modellen naarapp.asar.unpacked/- Hierdoor zijn ze tijdens runtime toegankelijk via bestandssysteempaden
- Met de JavaScript-code worden paden automatisch aangepast (zie de
app.asarbovenstaande →app.asar.unpackedvervanging)
ignore- Uitgesloten van het uiteindelijke pakket:-
.winapp/- SDK-pakketten en -headers (niet nodig tijdens runtime) -
.msixbestanden - Verpakte uitvoer -
winMlAddon/bronbestanden: alleen dedist/map met gecompileerde binaire bestanden behouden
-
Opmerking
Als u een ander verpakkingshulpprogramma gebruikt (electron-builder, enzovoort), moet u vergelijkbare instellingen configureren voor het uitpakken van systeemeigen afhankelijkheden en het uitsluiten van ontwikkelbestanden. Raadpleeg de documentatie van uw packager voor ASAR-uitpakopties.
4. Afbeeldingsclassificatie
De ClassifyImage methode verwerkt een afbeelding en retourneert voorspellingen:
[JSExport]
public async Task<Prediction[]> ClassifyImage(string imagePath)
{
// Loads the image, preprocesses it, and runs inference
// Returns top predictions with labels and confidence scores
}
De volledige implementatie verwerkt het volgende:
- Afbeelding laden en vooraf verwerken (formaat wijzigen, normaliseren)
- De modeldeductie uitvoeren
- Resultaten na de verwerking om de beste voorspellingen te krijgen met labels en betrouwbaarheidsscores
Opmerking
De volledige broncode bevat voorverwerking van afbeeldingen, het maken van tensor en het parseren van resultaten. Controleer de voorbeeld-implementatie op alle details.
De code begrijpen
De invoegtoepassing biedt de volgende hoofdfuncties:
- CreateAsync - Initialiseert de invoegtoepassing en laadt het SqueezeNet-model
- ClassifyImage : neemt een afbeeldingspad en retourneert classificatievoorspellingen
WinML selecteert automatisch het beste uitvoeringsapparaat (CPU, GPU of NPU) op basis van beschikbaarheid.
Stap 5: de C#-invoegtoepassing bouwen
Bouw nu de invoegtoepassing:
npm run build-winMlAddon
Hiermee compileert u uw C#-code met behulp van systeemeigen AOT (compilatie vooraf), die:
- Maakt een
.nodebinaire bestand (native addon formaat) - Verwijdert ongebruikte code voor een kleinere bundel.
- Vereist geen .NET-runtime op doelcomputers.
- Biedt systeemeigen prestaties
De gecompileerde invoegtoepassing bevindt zich in winMlAddon/dist/winMlAddon.node.
Stap 6: De invoegtoepassing testen
We gaan nu testen of de invoegtoepassing werkt door deze aan te roepen vanuit het hoofdproces. Open src/main.js en volg deze stappen:
6.1. De invoegtoepassing laden
Voeg bovenaan de vereiste instructies toe:
const winMlAddon = require('../winMlAddon/dist/winMlAddon.node');
6.2. Een testfunctie maken
Voeg deze functie toe om afbeeldingsclassificatie te testen:
const testWinML = async () => {
console.log('Testing WinML addon...');
try {
let projectRoot = path.join(__dirname, '..');
// Adjust path for packaged apps
if (projectRoot.includes('app.asar')) {
projectRoot = projectRoot.replace('app.asar', 'app.asar.unpacked');
}
const addon = await winMlAddon.Addon.createAsync(projectRoot);
console.log('Model loaded successfully!');
// Classify a sample image
const imagePath = path.join(projectRoot, 'test-images', 'sample.jpg');
const predictions = await addon.classifyImage(imagePath);
console.log('Top predictions:');
predictions.slice(0, 5).forEach((pred, i) => {
console.log(`${i + 1}. ${pred.label}: ${(pred.confidence * 100).toFixed(2)}%`);
});
} catch (error) {
console.error('Error testing WinML:', error.message);
}
};
Belangrijkste punten:
- De padaanpassing (
app.asar→app.asar.unpacked) zorgt ervoor dat de code werkt in zowel ontwikkel- als verpakte apps - Hiermee worden de uitgepakte systeemeigen bestanden geopend die zijn geconfigureerd in
forge.config.js
6.3. De testfunctie aanroepen
Voeg deze regel toe aan het einde van de createWindow() functie:
testWinML();
6.4. Testafbeeldingen voorbereiden
Afbeeldingsclassificatie testen:
-
test-images/Een map maken in de hoofdmap van uw project - Voeg een testafbeelding toe met de naam
sample.jpg(de code verwacht deze exacte bestandsnaam) - Het SqueezeNet-model herkent 1000 verschillende ImageNet-klassen (dieren, objecten, scènes, enzovoort)
Wanneer u de app uitvoert, ziet u de classificatieresultaten in de console.
Tip
Zie het electron-winml-voorbeeld voor een volledige implementatie met IPC-handlers, dialoogvensters voor bestandsselectie en een gebruikersinterface.
Stap 7: Foutopsporingsidentiteit bijwerken
Om ervoor te zorgen dat de Windows App SDK is geladen en beschikbaar is voor gebruik, moeten we ervoor zorgen dat we de foutopsporingsidentiteit instellen die ervoor zorgt dat het framework wordt geladen wanneer onze app wordt uitgevoerd. Telkens wanneer u Package.appxmanifest wijzigt of bronnen wijzigt die in het manifest worden genoemd (zoals app-pictogrammen), moet u de debug-identiteit van uw app bijwerken. Rennen:
npx winapp node add-electron-debug-identity
Deze opdracht:
- Leest uw
Package.appxmanifestgegevens voor het ophalen van app-details en -mogelijkheden - Registreert
electron.exein uwnode_modulesmet een tijdelijke identiteit - Hiermee kunt u API's waarvoor authenticatie vereist is testen zonder volledige MSIX-verpakkingen
Opmerking
Deze opdracht maakt al deel uit van het postinstall script dat we in de installatiehandleiding hebben toegevoegd, dus deze wordt automatisch uitgevoerd na npm install. U moet deze echter handmatig uitvoeren wanneer u het volgende doet:
- Wijzigen
Package.appxmanifest(mogelijkheden, identiteit of eigenschappen wijzigen) - App-assets bijwerken (pictogrammen, logo's, enzovoort)
Voer nu uw app uit:
npm start
Controleer de console-uitvoer. U ziet nu de WinML-testresultaten.
⚠️ Bekend probleem: app-crashes of een leeg venster (klik om uit te vouwen)
Er is een bekende Windows-bug bij sparse packaging van Electron-toepassingen die ervoor zorgt dat de app vastloopt bij het starten of geen webinhoud weergeeft. Het probleem is opgelost in Windows, maar is nog niet doorgegeven aan alle apparaten.
Zie inrichting van de ontwikkelomgeving voor een tijdelijke oplossing.
Volgende stappen
Gefeliciteerd! U hebt een systeemeigen invoegtoepassing gemaakt waarmee machine learning-modellen kunnen worden uitgevoerd met WinML. 🎉
U kunt nu het volgende doen:
- Uw app voor distributie verpakken - Maak een MSIX-pakket dat u kunt distribueren
Of bekijk andere handleidingen:
- Een PhiSilium-invoegtoepassing maken - Meer informatie over het gebruik van de Phi Silicium AI-API
- Overzicht Aan de slag - Ga terug naar de hoofdhandleiding
Aanpassen voor uw model
Als u uw ONNX-model volledig wilt integreren, moet u het volgende doen:
- Inzicht in de invoer van uw model : afbeeldingen, tensoren, reeksen, enzovoort.
- Juiste invoerbindingen maken : converteer uw gegevens naar de indeling die WinML verwacht
- De uitvoer verwerken: de voorspellingen van het model parseren en interpreteren
- Fouten probleemloos afhandelen - Model laden en inferentie kunnen mislukken
Aanvullende informatiebronnen
- WinML-documentatie - Officiële WinML-documentatie
- documentatie voor winapp CLI - Volledige CLI-verwijzing
- Voorbeeld van Electron-app - Volledig werkvoorbeeld
- AI Dev Gallery - Voorbeeldgalerie van alle AI-API's
- Windows App SDK Samples - Verzameling van Windows App SDK voorbeelden
- node-api-dotnet - C# ↔ JavaScript-interop-bibliotheek
Troubleshooting
Build mislukt met NU1010: PackageReference-items definiëren geen bijbehorende PackageVersion
Zorg ervoor dat alle pakketten waarnaar wordt verwezen winMlAddon.csproj overeenkomende vermeldingen bevatten in Directory.packages.props. Zie stap 3 voor de volledige lijst met vereiste pakketten.
'geen geldige Win32-toepassing' bij het laden van de invoegtoepassing
Dit betekent dat de invoegtoepassing is gebouwd voor een andere architectuur dan uw Node.js/Electron-runtime. Controleer de architectuur van uw Node.js:
node -e "console.log(process.arch)"
Bouw vervolgens de invoegtoepassing opnieuw met het overeenkomende doel:
# For x64 Node.js:
dotnet publish ./winMlAddon/winMlAddon.csproj -c Release -r win-x64
# For ARM64 Node.js:
dotnet publish ./winMlAddon/winMlAddon.csproj -c Release -r win-arm64
Als u onlangs uw Node.js-installatie hebt gewijzigd, installeert u deze ook opnieuw node_modules om het overeenkomende binaire electronenbestand op te halen:
rm -rf node_modules package-lock.json
npm install
Krijg hulp
- Hebt u een fout gevonden?Een probleem indienen
- Vragen over WinML? Raadpleeg de WinML-documentatie
Veel plezier met machine learning! 🤖
Windows developer