diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c1ee5..cb944cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ # Change Log +## 1.1.0 + +### ✨ New + +- Add support for non-standard installation paths on Windows. + ## 1.0.1 ### ♻️ Update diff --git a/src/commands/restart.ts b/src/commands/restart.ts index ecf978f..efb8aa9 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -15,7 +15,7 @@ export const restart = command(async ({ uuid }, output) => { return output.error("Restarting failed").log(`Plugin not found: ${uuid}`).exit(1); } - const appPath = `"${getStreamDeckPath()}"`; + const appPath = `"${await getStreamDeckPath()}"`; // When Stream Deck isn't running, start it. if (!(await isStreamDeckRunning())) { diff --git a/src/commands/stop.ts b/src/commands/stop.ts index 1ed6045..8fba7b3 100644 --- a/src/commands/stop.ts +++ b/src/commands/stop.ts @@ -21,7 +21,7 @@ export const stop = command(async ({ uuid }, output) => { } // Stop the plugin. - await run(`"${getStreamDeckPath()}"`, ["-s", uuid]); + await run(`"${await getStreamDeckPath()}"`, ["-s", uuid]); output.success(`Stopped ${chalk.green(uuid)}`); }); diff --git a/src/stream-deck.ts b/src/stream-deck.ts index 73ad611..0cbcf4a 100644 --- a/src/stream-deck.ts +++ b/src/stream-deck.ts @@ -1,7 +1,8 @@ import find from "find-process"; -import { Dirent, readdirSync, readlinkSync } from "node:fs"; +import { Dirent, existsSync, readdirSync, readlinkSync } from "node:fs"; import os from "node:os"; import { basename, join, resolve } from "node:path"; +import { Registry } from "rage-edit"; const PLUGIN_SUFFIX = ".sdPlugin"; @@ -58,20 +59,48 @@ export function isPluginInstalled(uuid: string): boolean { * Gets the path to the Stream Deck application. * @returns The path. */ -export function getStreamDeckPath(): string { - if (os.platform() === "darwin") { - return "/Applications/Elgato Stream Deck.app/Contents/MacOS/Stream Deck"; - } else { - return "C:\\Program Files\\Elgato\\StreamDeck\\StreamDeck.exe"; +export const getStreamDeckPath = ((): (() => Promise) => { + let appPath: string | undefined = undefined; + return async () => (appPath ??= await __getStreamDeckPath()); + + /** + * Gets the path to the Stream Deck application. + * @returns The path. + */ + async function __getStreamDeckPath(): Promise { + if (os.platform() === "darwin") { + return "/Applications/Elgato Stream Deck.app/Contents/MacOS/Stream Deck"; + } else { + // Before checking the registry, check if the default path exists. + const defaultWinPath = "C:\\Program Files\\Elgato\\StreamDeck\\StreamDeck.exe"; + if (existsSync(defaultWinPath)) { + return defaultWinPath; + } + + // Otherwise, attempt to get the installation directory from the registry. + const registryValue = await Registry.get( + "HKEY_CURRENT_USER\\Software\\Elgato Systems GmbH\\StreamDeck", + "InstallDir", + ); + + if (registryValue && typeof registryValue === "string") { + const winPath = join(registryValue, "StreamDeck.exe"); + if (existsSync(winPath)) { + return winPath; + } + } + + throw new Error("StreamDeck.exe could not be found"); + } } -} +})(); /** * Determines if the Stream Deck application is currently running. * @returns `true` when the application is running; otherwise `false`. */ export async function isStreamDeckRunning(): Promise { - const appPath = getStreamDeckPath(); + const appPath = await getStreamDeckPath(); if (os.platform() === "darwin") { const processes = await find("name", "Elgato Stream Deck"); diff --git a/src/types/rage-edit.d.ts b/src/types/rage-edit.d.ts index f680362..91b8049 100644 --- a/src/types/rage-edit.d.ts +++ b/src/types/rage-edit.d.ts @@ -1,5 +1,13 @@ declare module "rage-edit" { export const Registry: { + /** + * Gets the specified registry key value. + * @param path Path to the registry entry. + * @param name Name of the registry entry. + * @returns Data stored in the registry entry. + */ + get(path: string, name: string): Promise; + /** * Sets the specified registry key. * @param path Path to the registry entry.