Fix VirtViewer detection on Windows + manual path override

VirtViewer's installer folder name includes the version number
(e.g. "VirtViewer v11.0-256"), so the previous hardcoded path never
matched a real install. Now scans Program Files for any VirtViewer*
folder, and adds a Settings dialog (Windows only) to pick the
remote-viewer.exe path manually as a fallback.
This commit is contained in:
2026-07-06 10:02:53 +02:00
parent 98adbefefe
commit a0e7aa8f52
6 changed files with 188 additions and 13 deletions
+65 -12
View File
@@ -155,6 +155,28 @@ ipcMain.handle('proxmox:connect', async (_e, { node, vmid }) => {
}
});
// ---------- IPC: settings ----------
ipcMain.handle('settings:platform', () => process.platform);
ipcMain.handle('settings:getViewerPath', () => store.get('viewerPath', null));
ipcMain.handle('settings:clearViewerPath', () => {
store.delete('viewerPath');
});
ipcMain.handle('settings:browseViewerPath', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
title: 'remote-viewer.exe auswählen',
properties: ['openFile'],
filters: [{ name: 'remote-viewer', extensions: ['exe'] }],
});
if (result.canceled || result.filePaths.length === 0) return null;
const chosen = result.filePaths[0];
store.set('viewerPath', chosen);
return chosen;
});
// ---------- SPICE helpers ----------
function buildVVFile(params, vmid) {
@@ -187,24 +209,55 @@ function buildVVFile(params, vmid) {
return vvPath;
}
// VirtViewer's Windows installer names its folder after the bundled version
// (e.g. "VirtViewer v11.0-256"), so a fixed path breaks on every version bump.
// Scan the two Program Files dirs for any "VirtViewer*" folder instead.
function findWindowsViewerCandidates() {
const roots = [
process.env['ProgramFiles'] || 'C:\\Program Files',
process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)',
];
const found = [];
for (const root of roots) {
let entries;
try {
entries = fs.readdirSync(root, { withFileTypes: true });
} catch {
continue;
}
for (const entry of entries) {
if (!entry.isDirectory() || !/^virtviewer/i.test(entry.name)) continue;
const exe = path.join(root, entry.name, 'bin', 'remote-viewer.exe');
if (fs.existsSync(exe)) found.push(exe);
}
}
return found;
}
function launchRemoteViewer(vvPath) {
const candidates =
process.platform === 'win32'
? [
'remote-viewer',
path.join('C:', 'Program Files', 'VirtViewer', 'bin', 'remote-viewer.exe'),
path.join('C:', 'Program Files (x86)', 'VirtViewer', 'bin', 'remote-viewer.exe'),
]
: ['remote-viewer', 'virt-viewer'];
let candidates;
if (process.platform === 'win32') {
const customPath = store.get('viewerPath', null);
candidates = [
...(customPath ? [customPath] : []),
'remote-viewer',
...findWindowsViewerCandidates(),
];
} else {
candidates = ['remote-viewer', 'virt-viewer'];
}
function tryNext(i) {
if (i >= candidates.length) {
const hint =
process.platform === 'win32'
? 'Windows: https://virt-manager.org/download/\n\n' +
'Falls VirtViewer an einem nicht-standardmäßigen Ort installiert ist, ' +
'trage den Pfad unter „Einstellungen → Viewer-Pfad" ein.'
: 'Linux: sudo apt install virt-viewer';
dialog.showErrorBox(
'remote-viewer nicht gefunden',
'Bitte installiere virt-viewer:\n\n' +
' Linux: sudo apt install virt-viewer\n' +
' Windows: https://virt-manager.org/download/\n\n' +
'Danach bitte erneut verbinden.'
'Bitte installiere virt-viewer:\n\n' + hint + '\n\nDanach bitte erneut verbinden.'
);
return;
}