Das shell-Modul liefert OS-typische Aktionen ohne Umweg über child_process: Links im Browser öffnen, Dateien im Standard-Programm starten, Files im Finder/Explorer zeigen, Files in den Papierkorb verschieben. Klein, aber sehr nützlich für die Standard-Use-Cases.
URL im Browser öffnen — openExternal
import { shell } from 'electron';
await shell.openExternal('https://example.com');
await shell.openExternal('mailto:hello@example.com');
await shell.openExternal('tel:+49123456789');URL wird im Standard-Browser des Users geöffnet — nicht in der App. Klassischer Use-Case: „Privacy Policy" anklickbar machen, ohne den Browser nachzuahmen.
Sicherheits-Warnung: niemals User-Input direkt an openExternal übergeben — javascript:-URLs könnten je nach OS gefährlich sein (auf manchen Linux-Konfigs).
function safeOpenExternal(url) {
try {
const u = new URL(url);
if (['http:', 'https:', 'mailto:'].includes(u.protocol)) {
return shell.openExternal(url);
}
} catch {}
console.warn('Blockierte URL:', url);
}Datei mit Standard-App öffnen — openPath
// PDF mit Standard-PDF-Viewer öffnen
const error = await shell.openPath('/Users/anna/docs/report.pdf');
if (error) console.error('Fehler:', error);
// Funktioniert auch mit Verzeichnissen — öffnet im Finder/Explorer
await shell.openPath('/Users/anna/Documents');openPath gibt bei Fehler einen String zurück (nicht throw), bei Erfolg einen leeren String. Eigentümliches API, aber bewusst so — viele Fehler sind nicht-kritisch.
Datei im Finder/Explorer zeigen — showItemInFolder
// Öffnet den Ordner UND markiert die Datei darin
shell.showItemInFolder('/Users/anna/docs/report.pdf');Klassischer Use-Case: „Im Finder zeigen"-Button nach einem Download. macOS zeigt Finder mit der Datei selektiert, Windows-Explorer macht's analog.
showItemInFolder ist sync und kein Promise.
In den Papierkorb verschieben — trashItem
try {
await shell.trashItem('/Users/anna/docs/old-report.pdf');
console.log('In Papierkorb verschoben');
} catch (err) {
console.error('Fehler:', err);
}Sicherer als fs.unlink — Datei landet im Papierkorb (macOS-Trash, Windows-Recycle-Bin, Linux-Distro-spezifisch), User kann sie wiederherstellen.
Pragmatisch: für „User hat versehentlich gelöscht"-Szenarien immer trashItem statt unlink.
System-Beep
shell.beep();Spielt den OS-Standard-Beep ab. Selten nötig, aber bei Custom-UI manchmal sinnvoll als Fehler-Feedback.
Aus dem Renderer aufrufen
Wie alle Main-APIs: über IPC.
ipcMain.handle('shell:open-external', (_event, url) => {
// Validation
try {
const u = new URL(url);
if (!['http:', 'https:'].includes(u.protocol)) return false;
return shell.openExternal(url);
} catch {
return false;
}
});contextBridge.exposeInMainWorld('api', {
openExternal: (url) => ipcRenderer.invoke('shell:open-external', url)
});Wichtig: immer im Main-Handler validieren. Renderer-Input ist nicht trusted — eine kompromittierte Seite könnte sonst beliebige URLs durchschleusen.
Besonderheiten
openExternal öffnet im STANDARD-Browser, nicht in der App.
User-Erwartung: externe Links → externer Browser. Wer Links innerhalb der Electron-App öffnet, frustriert User (kein Bookmark, kein History etc.). openExternal ist der idiomatische Weg.
trashItem statt fs.unlink — sicherer.
User können Reverse-Aktionen erwarten. unlink ist endgültig, trashItem landet im Papierkorb. Pragmatisch: alle User-getriggerten Lösch-Aktionen via trashItem. Nur interne Cleanup-Logik (Caches, Logs) via unlink.
openPath gibt Fehler als String, nicht via throw.
Eigentümliches API: const error = await shell.openPath(path) — leer bei Erfolg, mit Text bei Fehler. Anders als der Rest, der entweder throw't oder Boolean liefert.
URLs IMMER im Main validieren.
Auch wenn der Preload schon „cleane" Funktionen exponiert: Renderer ist nicht trusted. Bei openExternal-Forwarding strict validieren — nur http, https, mailto durchlassen. Sonst Risiko: kompromittierte Webseite öffnet file://-Pfade oder Custom-Protocols.
showItemInFolder ist sync — keine Promise.
Anders als die meisten Async-APIs. Pragmatisch: macht den User-Klick sofort sichtbar, ohne Latency. Nur das Öffnen des Finder-Fensters folgt asynchron.
Linux: openPath verhält sich Distro-abhängig.
Auf Linux ruft openPath xdg-open auf — was je nach Desktop-Environment unterschiedliche Programme sind. Bei kritischen Workflows besser eigene Logik, was geöffnet wird.