Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Handbuch erfahren Sie, wie Sie ein systemeigenes C#-Addon erstellen, das Windows Machine Learning (WinML) in Ihrer Electron-App verwendet. Mit WinML können Sie machine learning Modelle (ONNX-Format) lokal auf Windows-Geräten für Aufgaben wie Bildklassifizierung, Objekterkennung und vieles mehr ausführen.
Voraussetzungen
Bevor Sie diesen Leitfaden starten, stellen Sie sicher, dass Sie folgendes haben:
- Einrichtung der Entwicklungsumgebung abgeschlossen
- Windows 11 oder Windows 10 (Version 1809 oder höher)
Hinweis
WinML wird auf jedem Windows 10 (1809+) oder Windows 11 Gerät ausgeführt. Für eine optimale Leistung werden Geräte mit GPUs oder NPUs empfohlen, die API funktioniert jedoch auch auf cpu.
Wichtig
Für das WinML-Addon ist das experimental Windows App SDK erforderlich. Wenn Sie während winapp init im Setup-Handbuch "Stable SDKs" ausgewählt haben, müssen Sie Ihre SDK-Version aktualisieren. Bearbeiten Sie winapp.yaml, und ändern Sie die version Microsoft.WindowsAppSDK in 2.0.0-experimental3, und führen Sie dann npx winapp restore zum Aktualisieren aus.
Schritt 1: Erstellen eines nativen C#-Add-Ons
Erstellen wir nun ein systemeigenes Addon, das WinML-APIs verwendet. Wir verwenden eine C#-Vorlage, die node-api-dotnet nutzt, um JavaScript und C# zu überbrücken.
npx winapp node create-addon --template cs --name winMlAddon
Dadurch wird ein winMlAddon/ Ordner mit:
-
addon.cs– Ihr C#-Code, der WinML-APIs aufruft -
winMlAddon.csproj– Project Datei mit Verweisen auf Windows SDK und Windows App SDK -
README.md- Dokumentation zur Verwendung des Add-Ons
Der Befehl fügt Ihrem Addon ein build-winMlAddon-Skript zum Erstellen des Addons und ein clean-winMlAddon-Skript zum Bereinigen von Build-Artefakten hinzu.
{
"scripts": {
"build-winMlAddon": "dotnet publish ./winMlAddon/winMlAddon.csproj -c Release",
"clean-winMlAddon": "dotnet clean ./winMlAddon/winMlAddon.csproj"
}
}
Die Vorlage enthält automatisch Verweise auf beide SDKs, sodass Sie sofort mit dem Aufrufen Windows APIs beginnen können!
Überprüfen wir, ob alles ordnungsgemäß eingerichtet ist, indem wir das Add-On erstellen:
# Build the C# addon
npm run build-winMlAddon
Hinweis
Sie können auch ein C++-Add-On mit npx winapp node create-addon (ohne das --template Flag) erstellen. C++-Addons verwenden node-addon-api und bieten direkten Zugriff auf Windows APIs mit maximaler Leistung. Weitere Optionen finden Sie im C++-Benachrichtigungs-Addon-Handbuch für eine exemplarische Vorgehensweise oder die vollständige Befehlsdokumentation .
Schritt 2: Herunterladen des SqueezeNet-Modells und Abrufen von Beispielcode
Wir verwenden das Beispiel zum Klassifizieren von Bildern aus der AI Dev Gallery als Referenz. In diesem Beispiel wird das SqueezeNet 1.1-Modell für die Bildklassifizierung verwendet.
2.1. Herunterladen des Modells
- Installieren des AI Dev Gallery
- Navigieren Sie zum Beispiel "Klassifizieren von Bildern" .
- Herunterladen des SqueezeNet 1.1-Modells (es unterstützt CPU, GPU und NPU)
- Klicken Sie auf "Enthaltenden Ordner öffnen ", um die
.onnxDatei zu suchen.
- Kopieren Sie die Datei
squeezenet1.1.onnxin einenmodels/Ordner im Projektstammverzeichnis.
Hinweis
Das Modell kann auch direkt aus dem ONNX Model Zoo GitHub Repo heruntergeladen werden
Schritt 3: Hinzufügen erforderlicher NuGet-Pakete
Bevor Sie den WinML-Code hinzufügen, müssen wir zusätzliche NuGet-Pakete hinzufügen, die für die Bildverarbeitung, ONNX-Runtime und GenAI-Unterstützung erforderlich sind.
3.1. Update Directory.packages.props
Fügen Sie die folgenden Paketversionen zur Directory.packages.props Datei im Stammverzeichnis Ihres Projekts hinzu (sollte erstellt worden sein, wenn Sie das Addon erstellt haben):
<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 aktualisieren
Öffnen Sie winMlAddon/winMlAddon.csproj und fügen Sie die Paketverweise zu <ItemGroup> hinzu.
<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>
Was die folgenden Pakete tun:
- Microsoft.ML.OnnxRuntime.Extensions – Stellt zusätzliche Operatoren und Hilfsprogramme für DIE ONNX-Runtime bereit.
- System.Drawing.Common – Ermöglicht das Laden und Bearbeiten von Bildern für die Vorverarbeitung.
- Microsoft. Extensions.AI - KI-Abstraktionen für .NET
- Microsoft.ML.OnnxRuntimeGenAI.Managed – Verwaltete Bindungen für ONNX Runtime GenAI
- Microsoft.ML.OnnxRuntimeGenAI.WinML - WinML-Integration für ONNX Runtime GenAI
Schritt 4: Hinzufügen des Beispielcodes
Die AI Dev Gallery zeigt die vollständige Implementierung für die Bildklassifizierung mit SqueezeNet:
Wir haben diesen Code für Electron angepasst, und Sie finden die vollständige Implementierung im Elektronen-Winml-Beispiel. Der winMlAddon/ Ordner enthält den geänderten Code aus dem AI Dev Gallery.
Kopieren Sie den gesamten winMlAddon/ Ordner aus Samples/electron-winml/winMlAddon/ in Ihr Projektwurzelverzeichnis und ersetzen Sie den in Schritt 1 erstellten Ordner. Das Beispiel enthält mehrere Dateien darüber hinaus addon.cs (Hilfsklassen in Utils/, einen Chatclient usw.), die für das Addon zum Erstellen und Ausführen erforderlich sind.
Wichtig
Sie müssen den gesamten Ordner kopieren, nicht nur addon.cs. Das Addon hängt von Hilfsdateien im Utils/ Unterordner (Prediction.cs, ImageNet.cs, BitmapFunctions.csusw.) ab.
Wichtige Implementierungsdetails
Lassen Sie uns die wichtigen Teile der Implementierung und der wichtigsten Unterschiede im AI Dev Gallery-Code hervorheben:
1. Project Stammpfadanforderung
Im Gegensatz zum AI Dev Gallery-Code erfordert unser Electron-Addon den JavaScript-Code, um den Projektstammpfad zu übergeben. Dies ist erforderlich, da:
- Das Addon muss die ONNX-Modelldatei im
models/Ordner suchen. - Systemeigene Abhängigkeiten (DLLs) müssen aus bestimmten Verzeichnissen geladen werden
[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;
}
Dadurch wird automatisch der beste Ausführungsanbieter (CPU, GPU oder NPU) basierend auf Gerätefunktionen ausgewählt.
2. Vorabladen nativer Abhängigkeiten
Das Addon enthält eine PreloadNativeDependencies() Methode zum Laden erforderlicher DLLs. Dieser Ansatz funktioniert sowohl für Entwicklungs- als auch für Produktionsszenarien , ohne DLLs in den Projektstamm kopieren zu müssen:
private void PreloadNativeDependencies()
{
// Loads required DLLs from the winMlAddon build output
// This ensures dependencies are available regardless of the execution context
}
Dies wird während der Initialisierung aufgerufen, bevor das Modell geladen wird, um sicherzustellen, dass alle systemeigenen Bibliotheken verfügbar sind.
3. Konfigurieren der Elektronenschmiede für Verpackungen
Um sicherzustellen, dass das Addon in Produktionsbuilds ordnungsgemäß funktioniert, müssen Sie den Packager für Folgendes konfigurieren:
- Entpacken systemeigener Dateien – DLLs, ONNX-Modelle und NODE-Dateien müssen außerhalb des ASAR-Archivs zugänglich sein
- Unnötige Dateien ausschließen – Halten Sie die Paketgröße klein, indem Sie Buildartefakte und temporäre Dateien ausschließen
Für Electron Forge aktualisieren Sie Ihre 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
};
Was dies bewirkt:
asar.unpack- Extrahiert DLLs, ausführbare Dateien, Node-Binärdateien und ONNX-Modelle inapp.asar.unpacked/- Dadurch können sie zur Laufzeit über Dateisystempfade zugänglich sein.
- Der JavaScript-Code passt Pfade automatisch an (siehe
app.asar→app.asar.unpackedErsetzung oben)
ignore- Schließt aus dem endgültigen Paket aus:-
.winapp/- SDK-Pakete und Header (zur Laufzeit nicht erforderlich) -
.msixDateien – Paketierte Ausgaben -
winMlAddon/Quelldateien – Behält nur dendist/Ordner mit kompilierten Binärdateien bei
-
Hinweis
Wenn Sie ein anderes Verpackungstool (Elektronen-Generator usw.) verwenden, müssen Sie ähnliche Einstellungen für das Entpacken systemeigener Abhängigkeiten konfigurieren und Entwicklungsdateien ausschließen. Überprüfen Sie die Dokumentation Ihres Packagers auf ASAR-Entpackungsoptionen.
4. Bildklassifizierung
Die ClassifyImage Methode verarbeitet ein Bild und gibt Vorhersagen zurück:
[JSExport]
public async Task<Prediction[]> ClassifyImage(string imagePath)
{
// Loads the image, preprocesses it, and runs inference
// Returns top predictions with labels and confidence scores
}
Die vollständige Implementierung behandelt:
- Laden und Vorverarbeitung von Bildern (Größenänderung, Normalisierung)
- Ausführen der Modellinferenz
- Ergebnisse nach der Verarbeitung, um Topvorhersagen mit Bezeichnungen und Konfidenzergebnissen zu erhalten
Hinweis
Der vollständige Quellcode enthält Bildvorverarbeitung, Tensorerstellung und Ergebnisanalyse. Überprüfen Sie die Beispielimplementierung auf alle Details.
Grundlegendes zum Code
Das Addon bietet die folgenden Hauptfunktionen:
- CreateAsync – Initialisiert das Addon und lädt das SqueezeNet-Modell.
- ClassificationImage – Übernimmt einen Bildpfad und gibt Klassifizierungsvorhersagen zurück.
WinML wählt automatisch das beste Ausführungsgerät (CPU, GPU oder NPU) basierend auf der Verfügbarkeit aus.
Schritt 5: Erstellen des C#-Add-Ons
Erstellen Sie nun das Addon:
npm run build-winMlAddon
Dadurch wird Ihr C#-Code mithilfe der nativen AOT (Ahead-of-Time-Kompilierung) kompiliert, die:
- Erstellt eine
.nodeBinärdatei (systemeigenes Addon-Format) - Kürzen von nicht verwendetem Code für eine kleinere Paketgröße
- Erfordert keine .NET-Laufzeitumgebung auf Zielcomputern
- Bietet systemeigene Leistung
Das kompilierte Addon wird in winMlAddon/dist/winMlAddon.node sein.
Schritt 6: Testen des Add-Ons
Jetzt testen wir das Addon, indem wir es aus dem Hauptprozess aufrufen. Öffnen Sie src/main.js und führen Sie dann die folgenden Schritte aus:
6.1. Laden des Add-Ons
Fügen Sie oben die erforderlichen Anweisungen hinzu.
const winMlAddon = require('../winMlAddon/dist/winMlAddon.node');
6.2. Erstellen einer Testfunktion
Fügen Sie diese Funktion zum Testen der Bildklassifizierung hinzu:
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);
}
};
Wichtige Punkte:
- Die Pfadanpassung (
app.asar→app.asar.unpacked) stellt sicher, dass der Code sowohl in der Entwicklung als auch in verpackten Apps funktioniert. - Dadurch wird auf die entpackten nativen Dateien zugegriffen, die in
forge.config.jskonfiguriert sind.
6.3. Aufrufen der Testfunktion
Fügen Sie diese Zeile am Ende der createWindow() Funktion hinzu:
testWinML();
6.4. Vorbereiten von Testbildern
So testen Sie die Bildklassifizierung:
- Erstellen eines
test-images/Ordners im Projektstamm - Hinzufügen eines Testbilds mit dem Namen
sample.jpg(der Code erwartet diesen genauen Dateinamen) - Das SqueezeNet-Modell erkennt 1000 verschiedene ImageNet-Klassen (Tiere, Objekte, Szenen usw.)
Wenn Sie die App ausführen, werden die Klassifizierungsergebnisse in der Konsole angezeigt!
Tip
Eine vollständige Implementierung mit IPC-Handlern, Dateiauswahldialogfeldern und einer Benutzeroberfläche finden Sie im Elektronen-Winml-Beispiel.
Schritt 7: Aktualisieren der Debugidentität
Um sicherzustellen, dass die Windows App SDK geladen und für die Verwendung verfügbar ist, müssen wir sicherstellen, dass die Debugidentität eingerichtet wird, die sicherstellt, dass das Framework bei jeder Ausführung unserer App geladen wird. Ebenso müssen Sie bei jeder Änderung Package.appxmanifest oder Änderung von Ressourcen, auf die im Manifest verwiesen wird (z. B. App-Symbole), die Debugidentität Ihrer App aktualisieren. Laufen:
npx winapp node add-electron-debug-identity
Dieser Befehl:
- Liest Ihre
Package.appxmanifest, um Details und Funktionen der App abzurufen. - Registriert
electron.exein Ihremnode_modulesmit einer temporären Identität. - Ermöglicht es Ihnen, identitätsrelevante APIs ohne vollständige MSIX-Verpackung zu testen.
Hinweis
Dieser Befehl ist bereits Teil des Skripts, das wir im postinstall Einrichtungsanleitung hinzugefügt haben, sodass es automatisch nach npm install ausgeführt wird. Sie müssen sie jedoch immer dann manuell ausführen, wenn Sie:
- Ändern
Package.appxmanifest(Ändern von Funktionen, Identitäten oder Eigenschaften) - Aktualisieren von App-Ressourcen (Symbole, Logos usw.)
Führen Sie nun Ihre App aus:
npm start
Überprüfen Sie die Konsolenausgabe – die WinML-Testergebnisse sollten angezeigt werden!
⚠– Bekanntes Problem: App stürzt ab oder leeres Fenster (zum Erweitern klicken)
Es gibt einen bekannten Windows-Fehler bei der sparsamen Verpackung von Electron-Anwendungen, was dazu führt, dass die App beim Start abstürzt oder keine Webinhalte rendert. Das Problem wurde in Windows behoben, wurde jedoch noch nicht an alle Geräte weitergegeben.
Informationen zur Problemumgehung finden Sie unter "Setup der Entwicklungsumgebung ".
Nächste Schritte
Herzlichen Glückwunsch! Sie haben erfolgreich ein systemeigenes Addon erstellt, das Machine Learning-Modelle mit WinML ausführen kann! 🎉
Jetzt sind Sie bereit für:
- Verpacken Ihrer App für Verteilung – Erstellen Eines MSIX-Pakets, das Sie verteilen können
Oder erkunden Sie andere Guides:
- Erstellen eines Phi-Silica-Addon - Erfahren Sie, wie Sie die Phi-Silica-KI-API verwenden
- Übersicht über erste Schritte – Zurück zum Hauptleitfaden
Anpassen für Ihr Modell
Um Ihr ONNX-Modell vollständig zu integrieren, müssen Sie:
- Verstehen der Eingaben Ihres Modells – Bilder, Tensoren, Sequenzen usw.
- Erstellen richtiger Eingabebindungen – Konvertieren Ihrer Daten in das erwartete WinML-Format
- Verarbeiten der Ausgaben – Analysieren und Interpretieren der Vorhersagen des Modells
- Fehler ordnungsgemäß behandeln – Modelllade- und Rückschlussfehler können fehlschlagen
Zusätzliche Ressourcen
- WinML-Dokumentation - Offizielle WinML-Dokumentation
- winapp CLI-Dokumentation - Vollständige CLI-Referenz
- Sample Electron App – Vollständiges Arbeitsbeispiel
- AI Dev Gallery – Beispielkatalog aller KI-APIs
- Windows App SDK Samples - Sammlung von Windows App SDK Beispielen
- node-api-dotnet – C# ↔ JavaScript-Interoperabilitätsbibliothek
Problembehandlung
Build schlägt mit NU1010 fehl: PackageReference-Elemente definieren keine entsprechende PackageVersion
Stellen Sie sicher, dass alle Pakete, auf die in winMlAddon.csproj verwiesen wird, übereinstimmende Einträge in Directory.packages.props haben. Eine vollständige Liste der erforderlichen Pakete finden Sie in Schritt 3.
"Keine gültige Win32-Anwendung" beim Laden des Add-Ons
Dies bedeutet, dass das Addon für eine andere Architektur als Ihre Node.js/Electron Runtime erstellt wurde. Überprüfen Sie Ihre Node.js Architektur:
node -e "console.log(process.arch)"
Erstellen Sie dann das Addon mit dem übereinstimmenden Ziel neu:
# 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
Wenn Sie Ihre Node.js-Installation kürzlich geändert haben, installieren Sie node_modules erneut, um die entsprechende Electron-Binärdatei zu erhalten.
rm -rf node_modules package-lock.json
npm install
Hilfe
- Ein Fehler gefunden?Ein Problem melden
- WinML-Fragen? Lesen Sie die WinML-Dokumentation
Glückliches maschinelles Lernen! 🤖
Windows developer