Appeler Windows API à partir de JavaScript (liaisons JS)

Ce guide vous montre comment appeler des API Windows, qu’il s’agisse du SDK d'application Windows ou du Windows SDK, directement depuis le code JavaScript de votre application Electron, sans module natif ni étape node-gyp / MSBuild. Vous allez ouvrir une boîte de dialogue native de sélection de fichiers (SDK d'application Windows), puis examiner l’image sélectionnée à l’aide des API de fichiers et d’imagerie du SDK Windows ajoutées via winapp.jsBindings.

Prerequisites

Avant de commencer ce guide, vérifiez que vous avez :

Étape 1 : Confirmer vos liaisons

Le programme d’installation a généré un répertoire .winapp/bindings/ à côté de vos sources — une paire .js + .d.ts pour chaque classe SDK d'application Windows générée, ainsi qu’un répertoire index.js qui les réexporte toutes :

.winapp/bindings/
├── index.js                  # entry — re-exports every emitted class
├── index.d.ts                # TS bundle
├── FileOpenPicker.js         # one pair of files per emitted class
├── FileOpenPicker.d.ts
├── PickerLocationId.js
├── PickerLocationId.d.ts
└── …

Étape 2 : Ajouter des API Windows SDK à vos liaisons

Les liaisons par défaut couvrent uniquement les API SDK d'application Windows. Pour ouvrir et décoder l’image choisie, nous avons également besoin de deux classes Windows SDK :

  • Windows.Storage.StorageFile — pour encapsuler un chemin d’accès au fichier.
  • Windows.Graphics.Imaging.BitmapDecoder — pour en lire les dimensions.

Ouvrez package.json et ajoutez un additionalWinmds tableau à l’intérieur du winapp.jsBindings bloc qui winapp init a créé :

// package.json
{
  "winapp": {
    "jsBindings": {
      "additionalWinmds": [
        { "namespace": "Windows.Storage", "classes": ["StorageFile"] },
        { "namespace": "Windows.Graphics.Imaging", "classes": ["BitmapDecoder"] }
      ]
    }
  }
}

Régénérez ensuite les liaisons :

npx winapp node generate-bindings

StorageFile.js, BitmapDecoder.jset les fichiers enum dont ils dépendent (FileAccessMode.js, BitmapPixelFormat.js, ...) apparaissent maintenant dans .winapp/bindings/.

Note

dynwinrt-codegen inclut automatiquement les types dépendants dont vous avez besoin pour appeler ces classes (par exemple IRandomAccessStream, retournés par StorageFile.openAsync), de sorte qu’il suffit généralement de ne sélectionner que les classes de point d’entrée.

Étape 3 : Appeler des API Windows à partir de votre code Electron

Toutes les classes générées sont exportées via #winapp/bindings:

Nécessite @microsoft/dynwinrt-codegen0.1.0-preview.8 — consultez Prise en main d’Electron pour les solutions de repli des projets plus anciens.

// src/index.js (Electron main, CommonJS)
const { app, BrowserWindow, ipcMain } = require('electron');
const {
  // Windows App SDK (default bindings)
  FileOpenPicker,
  PickerLocationId,
  PickerViewMode,
  // Windows SDK (added via additionalWinmds in Step 2)
  StorageFile,
  FileAccessMode,
  BitmapDecoder,
} = require('#winapp/bindings');

async function pickAndInspectImage(mainWindow) {
  // FileOpenPicker needs the parent window's HWND wrapped in a WindowId struct.
  // Electron's getNativeWindowHandle() returns an 8-byte buffer on 64-bit Windows.
  const hwnd = mainWindow.getNativeWindowHandle().readBigUInt64LE(0);

  const picker = FileOpenPicker.createInstance({ value: hwnd });
  picker.viewMode = PickerViewMode.Thumbnail;
  picker.suggestedStartLocation = PickerLocationId.PicturesLibrary;
  picker.fileTypeFilter.replaceAll(['.png', '.jpg', '.jpeg', '.gif']);

  const result = await picker.pickSingleFileAsync();
  if (!result?.path) return null; // User cancelled.

  // Use Windows SDK APIs to inspect the picked image.
  const file = await StorageFile.getFileFromPathAsync(result.path);
  const stream = await file.openAsync(FileAccessMode.Read);
  const decoder = await BitmapDecoder.createAsync(stream);

  return {
    path: result.path,
    width: decoder.pixelWidth,
    height: decoder.pixelHeight,
  };
}

// Expose it to the renderer via IPC so a button click can trigger the flow.
ipcMain.handle('pick-and-inspect-image', (event) => {
  const win = BrowserWindow.fromWebContents(event.sender);
  return pickAndInspectImage(win);
});

Ensuite, faites le lien avec le processus de rendu via votre script de préchargement :

// src/preload.js
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('winapp', {
  pickAndInspectImage: () => ipcRenderer.invoke('pick-and-inspect-image'),
});

Enfin, ajoutez un bouton à votre renderer et appelez window.winapp.pickAndInspectImage() lorsqu’il est cliqué sur :

<!-- src/index.html -->
<button id="pick">Pick an image</button>
<p id="result"></p>

<script>
  document.getElementById('pick').addEventListener('click', async () => {
    const info = await window.winapp.pickAndInspectImage();
    document.getElementById('result').textContent = info
      ? `${info.path} (${info.width}×${info.height})`
      : 'Cancelled';
  });
</script>

Étape 4 : l’exécuter

Pour que le sélecteur de fichiers fonctionne, vous devez vous assurer que votre application s’exécute avec une identité. Run:

npx winapp node add-electron-debug-identity

Note

Cette commande fait déjà partie du postinstall script que nous avons ajouté dans le guide d’installation. Elle s’exécute donc automatiquement après npm install. Toutefois, vous devez l’exécuter manuellement chaque fois que vous modifiez Package.appxmanifest, mettez à jour les ressources d’application ou réinstallez les dépendances.

À présent, démarrez l’application :

npm start

Cliquez sur le bouton : le sélecteur de fichiers Windows natif s’affiche et une fois que vous avez sélectionné une image, ses dimensions de chemin d’accès et de pixel s’affichent sous le bouton. 🎉 L’import depuis .winapp/bindings/ charge @microsoft/dynwinrt, qui redirige chaque appel vers l’API WinRT sous-jacente, de manière transparente pour votre code.

Prochaines étapes

Félicitations ! Vous appelez maintenant Windows API ( SDK d'application Windows et Windows SDK) directement à partir de JavaScript, sans module complémentaire natif et sans node-gyp étape de génération. 🎉

Vous êtes maintenant prêt à :

Ou explorez d’autres guides :

Ressources additionnelles