From 34d861c8477e8b4d2762a953fe4d7d0e873d475a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathis=20Dr=C3=B6ge?= Date: Sat, 9 Mar 2024 21:45:22 +0100 Subject: [PATCH] [Fix] Sideloaded games on Windows (#3562) * Support empty commandParts in callRunner's Windows case In case the array is empty, we have to make sure to not pass the parameter at all (otherwise PS will error out) This is used by sideloaded games * Correctly pass the "runner" path for sideloaded games Sideloaded games pass their executable path as the runner. Before, this was done a little incorrectly. Assume the selected executable is `C:\Windows\System32\cmd.exe`. Before, the runner would then be: { bin: `C:\Windows\System32\cmd.exe` dir: `C:\Windows\System32\` } callRunner then just `join`s together these paths, resulting in `C:\Windows\System32\C:\Windows\System32\cmd.exe`. This is obviously wrong and will not work. Now, we correctly pass just the bin for `bin` (`cmd.exe` in our example). This is also in-line with how regular runners work * Add "./" in callRunner directly This was somewhat flawed before; callRunner relied on an implementation detail of `splitPathAndName` (it adding "./" to the "bin"). The relevant code was now moved to callRunner itself --- src/backend/launcher.ts | 8 ++++++-- src/backend/storeManagers/storeManagerCommon/games.ts | 4 ++-- src/backend/utils.ts | 7 +------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/backend/launcher.ts b/src/backend/launcher.ts index 65fff09c76..2cc98bed69 100644 --- a/src/backend/launcher.ts +++ b/src/backend/launcher.ts @@ -993,6 +993,10 @@ async function callRunner( let bin = runner.bin let fullRunnerPath = join(runner.dir, bin) + // macOS/Linux: `spawn`ing an executable in the current working directory + // requires a "./" + if (!isWindows) bin = './' + bin + // On Windows: Use PowerShell's `Start-Process` to wait for the process and // its children to exit, provided PowerShell is available if (shouldUsePowerShell === null) @@ -1005,10 +1009,10 @@ async function callRunner( 'Start-Process', `"\`"${fullRunnerPath}\`""`, '-Wait', - '-ArgumentList', - argsAsString, '-NoNewWindow' ] + if (argsAsString) commandParts.push('-ArgumentList', argsAsString) + bin = fullRunnerPath = 'powershell' } diff --git a/src/backend/storeManagers/storeManagerCommon/games.ts b/src/backend/storeManagers/storeManagerCommon/games.ts index 3702b8b24f..a6c30cb9eb 100644 --- a/src/backend/storeManagers/storeManagerCommon/games.ts +++ b/src/backend/storeManagers/storeManagerCommon/games.ts @@ -8,7 +8,7 @@ import { LogPrefix, logWarning } from '../../logger/logger' -import { dirname } from 'path' +import { basename, dirname } from 'path' import { constants as FS_CONSTANTS } from 'graceful-fs' import i18next from 'i18next' import { @@ -220,7 +220,7 @@ export async function launchGame( { name: runner, logPrefix: LogPrefix.Backend, - bin: executable, + bin: basename(executable), dir: dirname(executable) }, { diff --git a/src/backend/utils.ts b/src/backend/utils.ts index e16d6983e9..58f4a35370 100644 --- a/src/backend/utils.ts +++ b/src/backend/utils.ts @@ -428,12 +428,7 @@ function showItemInFolder(item: string) { function splitPathAndName(fullPath: string): { dir: string; bin: string } { const dir = dirname(fullPath) - let bin = basename(fullPath) - // On Windows, you can just launch executables that are in the current working directory - // On Linux, you have to add a ./ - if (!isWindows) { - bin = './' + bin - } + const bin = basename(fullPath) // Make sure to always return this as `dir, bin` to not break path // resolution when using `join(...Object.values(...))` return { dir, bin }