Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här guiden visar hur du skapar ett internt C#-tillägg som använder Windows strojové učenie (WinML) i din Electron-app. Med WinML kan du köra machine learning modeller (ONNX-format) lokalt på Windows-enheter för uppgifter som bildklassificering, objektidentifiering med mera.
Förutsättningar
Kontrollera att du har gjort så här innan du startar den här guiden:
- Installationen av utvecklingsmiljön har slutförts
- Windows 11 eller Windows 10 (version 1809 eller senare)
Anmärkning
WinML körs på valfri Windows 10 (1809+) eller Windows 11 enhet. För bästa prestanda rekommenderas enheter med GPU:er eller NPU:er, men API:et fungerar även på CPU.
Viktigt!
WinML-tillägget kräver experimental Windows App SDK. Om du valde "Stabila SDK:er" under winapp init konfigurationsguiden måste du uppdatera SDK-versionen. Redigera winapp.yaml och ändra versionen Microsoft.WindowsAppSDK till 2.0.0-experimental3 och kör sedan npx winapp restore för att uppdatera.
Steg 1: Skapa ett internt C#-tillägg
Nu ska vi skapa ett internt tillägg som använder WinML-API:er. Vi använder en C#-mall som använder node-api-dotnet för att överbrygga JavaScript och C#.
npx winapp node create-addon --template cs --name winMlAddon
Då skapas en winMlAddon/ mapp med:
-
addon.cs– Din C#-kod som anropar WinML-API:er -
winMlAddon.csproj– Project fil med referenser till Windows SDK och Windows App SDK -
README.md– Dokumentation om hur du använder tillägget
Kommandot lägger också till ett build-winMlAddon skript i din package.json för byggande av tillägget och ett clean-winMlAddon skript för rensning av byggartefakter.
{
"scripts": {
"build-winMlAddon": "dotnet publish ./winMlAddon/winMlAddon.csproj -c Release",
"clean-winMlAddon": "dotnet clean ./winMlAddon/winMlAddon.csproj"
}
}
Mallen innehåller automatiskt referenser till båda SDK:erna, så att du omedelbart kan börja anropa Windows API:er!
Nu ska vi kontrollera att allt har konfigurerats korrekt genom att skapa tillägget:
# Build the C# addon
npm run build-winMlAddon
Anmärkning
Du kan också skapa ett C++-tillägg med ( npx winapp node create-addon utan --template flaggan). C++-tillägg använder node-addon-api och ger direkt åtkomst till Windows API:er med maximal prestanda. Se guiden C++-meddelandetillägg för en genomgång eller den fullständiga kommandodokumentationen för fler alternativ.
Steg 2: Ladda ned SqueezeNet-modellen och Hämta exempelkod
Vi använder exemplet Klassificera bild från AI Dev-galleriet som referens. Det här exemplet använder SqueezeNet 1.1-modellen för bildklassificering.
2.1. Ladda ned modellen
- Installera AI Dev-galleriet
- Gå till exempel på Klassificera bild
- Ladda ned SqueezeNet 1.1-modellen (den stöder CPU, GPU och NPU)
- Klicka på Öppna innehållande mapp för att hitta
.onnxfilen
- Kopiera filen
squeezenet1.1.onnxtill mappenmodels/i din project-rot
Anmärkning
Modellen kan också laddas ned direkt från ONNX Model Zoo GitHub lagringsplatsen
Steg 3: Lägg till nödvändiga NuGet-paket
Innan vi lägger till WinML-koden måste vi lägga till ytterligare NuGet-paket som krävs för bildbearbetning, ONNX Runtime och GenAI-stöd.
3.1. Uppdatera Directory.packages.props
Lägg till följande paketversioner i Directory.packages.props-filen som finns i roten av ditt projekt (den borde ha skapats när du skapade tillägget):
<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. Uppdatera winMlAddon.csproj
Öppna winMlAddon/winMlAddon.csproj och lägg till paketreferenserna i <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>
Vad dessa paket gör:
- Microsoft.ML.OnnxRuntime.Extensions – Tillhandahåller ytterligare operatorer och verktyg för ONNX Runtime
- System.Drawing.Common – Aktiverar inläsning och manipulering av avbildningar för förbearbetning
- Microsoft. Extensions.AI – AI-abstraktioner för .NET
- Microsoft.ML.OnnxRuntimeGenAI.Managed – Hanterade bindningar för ONNX Runtime GenAI
- Microsoft.ML.OnnxRuntimeGenAI.WinML – WinML-integrering för ONNX Runtime GenAI
Steg 4: Lägg till exempelkoden
AI Dev Gallery visar den fullständiga implementeringen för bildklassificering med SqueezeNet:
Vi har anpassat den här koden för Electron och du hittar den fullständiga implementeringen i elektron-winml-exemplet. Mappen winMlAddon/ innehåller den ändrade koden från AI Dev-galleriet.
Kopiera hela winMlAddon/ mappen från samples/electron-winml/winMlAddon/ till projektroten och ersätt den som skapades i steg 1. Exemplet innehåller flera filer utöver addon.cs (hjälpklasser i Utils/, en chattklient osv.) som krävs för att tillägget ska kunna byggas och köras.
Viktigt!
Du måste kopiera hela mappen, inte bara addon.cs. Tillägget är beroende av hjälpfiler i undermappen Utils/ (Prediction.cs, ImageNet.cs, BitmapFunctions.csosv.).
Viktig implementeringsinformation
Nu ska vi lyfta fram viktiga delar av implementeringen och viktiga skillnader från AI Dev Gallery-koden:
1. Krav på projektrotväg
Till skillnad från AI Dev Gallery-koden kräver vårt Electron-tillägg att JavaScript-koden skickar projektets rotsökväg. Detta är nödvändigt eftersom:
- Tillägget måste hitta ONNX-modellfilen i
models/mappen - Inbyggda beroenden (DLL: er) måste läsas in från specifika kataloger
[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;
}
Detta väljer automatiskt den bästa körningsprovidern (CPU, GPU eller NPU) baserat på enhetsfunktioner.
2. Förladda inbyggda beroenden
Tillägget innehåller en PreloadNativeDependencies() metod för att läsa in nödvändiga DLL:er. Den här metoden fungerar för både utvecklings- och produktionsscenarier utan att behöva kopiera DLL:er till projektroten:
private void PreloadNativeDependencies()
{
// Loads required DLLs from the winMlAddon build output
// This ensures dependencies are available regardless of the execution context
}
Detta anropas under initieringen innan modellen läses in, vilket säkerställer att alla interna bibliotek är tillgängliga.
3. Konfigurera Electron Forge för paketering
För att säkerställa att tillägget fungerar korrekt i produktionsversioner måste du konfigurera paketeraren för att:
- Packa upp inbyggda filer – DLL:er, ONNX-modeller och .node-filer måste vara tillgängliga utanför ASAR-arkivet
- Exkludera onödiga filer – Håll paketstorleken liten genom att exkludera byggartefakter och temporära filer
För Electron Forge: uppdatera din forge.config.js.
// 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
};
Vad detta gör:
asar.unpack– Extraherar DLL:er, körbara filer, .node-binärfiler och ONNX-modeller tillapp.asar.unpacked/- Detta gör dem tillgängliga under körning via filsystemsökvägar.
- JavaScript-koden justerar sökvägar automatiskt (se
app.asar→app.asar.unpackedersättning ovan)
ignore– Exkluderar från det slutliga paketet:-
.winapp/– SDK-paketen och huvudfilerna (behövs inte vid körning) -
.msixfiles – Paketerade utdata -
winMlAddon/källfiler – Behåller endastdist/mappen med kompilerade binärfiler
-
Anmärkning
Om du använder ett annat paketeringsverktyg (elektronbyggare osv.) måste du konfigurera liknande inställningar för att packa upp inbyggda beroenden och exkludera utvecklingsfiler. Kontrollera paketerarens dokumentation för asar-uppackningsalternativ.
4. Bildklassificering
Metoden ClassifyImage bearbetar en bild och returnerar förutsägelser:
[JSExport]
public async Task<Prediction[]> ClassifyImage(string imagePath)
{
// Loads the image, preprocesses it, and runs inference
// Returns top predictions with labels and confidence scores
}
Den fullständiga implementeringen hanterar:
- Bildinläsning och förbearbetning (storleksändring, normalisering)
- Utföra modellinferens
- Efterbearbetningsresultat för att få de bästa förutsägelserna med etiketter och konfidenspoäng
Anmärkning
Den fullständiga källkoden innehåller förbearbetning av avbildningar, tensor-skapande och resultatparsing. Kontrollera exempelimplementeringen för all information.
Förstå koden
Tillägget innehåller följande huvudfunktioner:
- CreateAsync – Initierar tillägget och läser in SqueezeNet-modellen
- ClassifyImage – Tar en bildsökväg och returnerar klassificeringsförutsägelser
WinML väljer automatiskt den bästa körningsenheten (CPU, GPU eller NPU) baserat på tillgänglighet.
Steg 5: Skapa C#-tillägget
Skapa nu tillägget:
npm run build-winMlAddon
Detta kompilerar din C#-kod med Native AOT (förkompilering), som:
- Skapar en
.nodebinär fil (internt tilläggsformat) - Minskar oanvänd kod för mindre paket.
- Kräver no .NET runtime på måldatorer
- Ger inbyggda prestanda
Det kompilerade tillägget finns i winMlAddon/dist/winMlAddon.node.
Steg 6: Testa tillägget
Nu ska vi testa att tillägget fungerar genom att anropa det från huvudprocessen. Öppna src/main.js och följ dessa steg:
6.1. Läs in tillägget
Lägg till require-satserna överst:
const winMlAddon = require('../winMlAddon/dist/winMlAddon.node');
6.2. Skapa en testfunktion
Lägg till den här funktionen för att testa bildklassificering:
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);
}
};
Viktiga punkter:
- Sökvägsjusteringen (
app.asar→app.asar.unpacked) säkerställer att koden fungerar i både utvecklingsappar och paketerade appar - Detta kommer åt de uppackade inhemska filerna som konfigurerats i
forge.config.js
6.3. Anropa testfunktionen
Lägg till den här raden i slutet av createWindow() funktionen:
testWinML();
6.4. Förbereda testbilder
Så här testar du bildklassificering:
- Skapa en
test-images/mapp i projektroten - Lägg till en testbild med namnet
sample.jpg(koden förväntar sig exakt det här filnamnet) - SqueezeNet-modellen identifierar 1 000 olika ImageNet-klasser (djur, objekt, scener osv.)
När du kör appen visas klassificeringsresultaten i konsolen!
Tips/Råd
En fullständig implementering med IPC-hanterare, dialogrutor för filval och ett användargränssnitt finns i exemplet electron-winml.
Steg 7: Uppdatera felsökningsidentitet
För att säkerställa att Windows App SDK läses in och är tillgänglig för användning måste vi se till att vi konfigurerar felsökningsidentitet som säkerställer att ramverket läses in när vår app körs. På samma sätt måste du uppdatera appens felsökningsidentitet när du ändrar Package.appxmanifest eller ändrar tillgångar som refereras i manifestet (till exempel appikoner). Run:
npx winapp node add-electron-debug-identity
Det här kommandot:
- Läser din
Package.appxmanifestför att hämta appinformation och funktioner -
electron.exeRegistrerar sig i dinnode_modulesmed en tillfällig identitet - Gör att du kan testa api:er som krävs för identitet utan fullständig MSIX-paketering
Anmärkning
Det här kommandot är redan en del av skriptet postinstall som vi lade till i installationsguiden, så det körs automatiskt efter npm install. Du måste dock köra den manuellt när du:
- Ändra
Package.appxmanifest(ändra funktioner, identitet eller egenskaper) - Uppdatera apptillgångar (ikoner, logotyper osv.)
Kör nu appen:
npm start
Kontrollera konsolens utdata – du bör se WinML-testresultatet!
⚠️ Känt problem: App kraschar eller tomt fönster (klicka för att expandera)
Det finns en känd Windows bugg med gles paketering av Elektronprogram som gör att appen kraschar vid start eller inte renderar webbinnehåll. Problemet har åtgärdats i Windows men har ännu inte spridits till alla enheter.
Se konfigurationen av utvecklingsmiljön för en lösning.
Nästa steg
Grattis! Du har skapat ett internt tillägg som kan köra maskininlärningsmodeller med WinML! 🎉
Nu är du redo att:
- Paketera din app för distribution – Skapa ett MSIX-paket som du kan distribuera
Eller utforska andra guider:
- Skapa ett Phi Silica-tillägg – Lär dig hur du använder PHI Silica AI API
- Översikt över komma igång – Gå tillbaka till huvudguiden
Anpassa för din modell
Om du vill integrera DIN ONNX-modell helt måste du:
- Förstå modellens indata – Bilder, tensorer, sekvenser osv.
- Skapa rätt indatabindningar – Konvertera dina data till det format som WinML förväntar sig
- Bearbeta utdata – Parsa och tolka modellens förutsägelser
- Hantera fel på ett korrekt sätt – Modellinläsning och slutsatsdragning kan misslyckas
Ytterligare resurser
- WinML-dokumentation – Officiell WinML-dokumentation
- winapp CLI-dokumentation – Fullständig CLI-referens
- Exempel på Electron-app – Komplett arbetsexempel
- AI Dev Gallery – exempelgalleri för alla AI-API:er
- Windows App SDK Samples – Samling Windows App SDK exempel
- node-api-dotnet – C# ↔ JavaScript-interop-bibliotek
Felsökning
Build misslyckas med NU1010: PackageReference-objekt definierar inte en motsvarande PackageVersion
Kontrollera att alla paket som refereras i winMlAddon.csproj har matchande poster i Directory.packages.props. Se Steg 3 för den fullständiga listan över nödvändiga paket.
"inte ett giltigt Win32-program" när tillägget läses in
Det innebär att tillägget har skapats för en annan arkitektur än din Node.js/Electron-körning. Kontrollera din Node.js arkitektur:
node -e "console.log(process.arch)"
Återskapa sedan tillägget med matchande mål:
# 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
Om du nyligen har ändrat installationen av Node.js installerar du även om node_modules för att hämta den matchande elektronbinärfilen:
rm -rf node_modules package-lock.json
npm install
Få hjälp
- Har du hittat en bugg?Skapa ett problem
- WinML-frågor? Kontrollera WinML-dokumentationen
Glad maskininlärning! 🤖
Windows developer