From 93835f58f3ba4595dce5f7966d3f6658b50de36f Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Tue, 10 Feb 2026 20:03:08 +0100 Subject: [PATCH] Keep Windows terminal open on error If scrcpy is launched by double-clicking scrcpy.exe in Windows Explorer, automatically set --pause-on-exit=if-error. Without this, the terminal would close immediately, preventing the user from seeing the error. Also remove scrcpy-console.bat, which is now useless. --- app/data/scrcpy-console.bat | 2 -- app/src/cli.c | 51 +++++++++++++++++++++++++++++++++---- app/src/cli.h | 1 + app/src/main.c | 2 +- doc/windows.md | 26 ++++++++----------- release/build_windows.sh | 1 - 6 files changed, 59 insertions(+), 24 deletions(-) delete mode 100644 app/data/scrcpy-console.bat diff --git a/app/data/scrcpy-console.bat b/app/data/scrcpy-console.bat deleted file mode 100644 index 0ea7619f..00000000 --- a/app/data/scrcpy-console.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -scrcpy.exe --pause-on-exit=if-error %* diff --git a/app/src/cli.c b/app/src/cli.c index 9c955fb5..c3a95583 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -3371,7 +3371,7 @@ sc_get_pause_on_exit(int argc, char *argv[]) { } if (arg[15] != '=') { // Invalid parameter, ignore - return SC_PAUSE_ON_EXIT_FALSE; + return SC_PAUSE_ON_EXIT_UNDEFINED; } const char *value = &arg[16]; if (!strcmp(value, "true")) { @@ -3380,14 +3380,44 @@ sc_get_pause_on_exit(int argc, char *argv[]) { if (!strcmp(value, "if-error")) { return SC_PAUSE_ON_EXIT_IF_ERROR; } - // Set to false, including when the value is invalid - return SC_PAUSE_ON_EXIT_FALSE; + if (!strcmp(value, "false")) { + return SC_PAUSE_ON_EXIT_FALSE; + } + return SC_PAUSE_ON_EXIT_UNDEFINED; } } - return SC_PAUSE_ON_EXIT_FALSE; + return SC_PAUSE_ON_EXIT_UNDEFINED; } +#ifdef _WIN32 +/** + * Attempt to detect whether the user launched scrcpy by double-clicking + * scrcpy.exe in Windows Explorer. + * + * If so, the console should remain open on error. + */ +static bool +scrcpy_launched_by_double_click(void) { + // No console window + if (GetConsoleWindow() == NULL) { + return false; + } + + // Must be interactive + if (!_isatty(_fileno(stdin)) || !_isatty(_fileno(stdout))) { + return false; + } + + // Check how many processes share the console + DWORD dummy; + DWORD count = GetConsoleProcessList(&dummy, 1); + + // Only this process attached, assume it was started by double-clicking + return count == 1; +} +#endif + bool scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { struct sc_getopt_adapter adapter; @@ -3401,11 +3431,22 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { sc_getopt_adapter_destroy(&adapter); - if (!ret && args->pause_on_exit == SC_PAUSE_ON_EXIT_FALSE) { + if (!ret && args->pause_on_exit == SC_PAUSE_ON_EXIT_UNDEFINED) { // Check if "--pause-on-exit" is present in the arguments list, because // it must be taken into account even if command line parsing failed args->pause_on_exit = sc_get_pause_on_exit(argc, argv); } + if (args->pause_on_exit == SC_PAUSE_ON_EXIT_UNDEFINED) { + args->pause_on_exit = SC_PAUSE_ON_EXIT_FALSE; +#ifdef _WIN32 + if (scrcpy_launched_by_double_click()) { + args->pause_on_exit = SC_PAUSE_ON_EXIT_IF_ERROR; + } +#endif + } + + assert(args->pause_on_exit != SC_PAUSE_ON_EXIT_UNDEFINED); + return ret; } diff --git a/app/src/cli.h b/app/src/cli.h index 6fd579a4..9aa38dc6 100644 --- a/app/src/cli.h +++ b/app/src/cli.h @@ -8,6 +8,7 @@ #include "options.h" enum sc_pause_on_exit { + SC_PAUSE_ON_EXIT_UNDEFINED, SC_PAUSE_ON_EXIT_TRUE, SC_PAUSE_ON_EXIT_FALSE, SC_PAUSE_ON_EXIT_IF_ERROR, diff --git a/app/src/main.c b/app/src/main.c index 7b728d73..3ab03243 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -39,7 +39,7 @@ main_scrcpy(int argc, char *argv[]) { .opts = scrcpy_options_default, .help = false, .version = false, - .pause_on_exit = SC_PAUSE_ON_EXIT_FALSE, + .pause_on_exit = SC_PAUSE_ON_EXIT_UNDEFINED, }; #ifndef NDEBUG diff --git a/doc/windows.md b/doc/windows.md index cdc30bdc..b0c4c5ca 100644 --- a/doc/windows.md +++ b/doc/windows.md @@ -72,18 +72,6 @@ Documentation for command line arguments is available: - `scrcpy --help` - on [github](/README.md) -To start scrcpy directly without opening a terminal, double-click on one of -these files: - - `scrcpy-console.bat`: start with a terminal open (it will close when scrcpy - terminates, unless an error occurs); - - `scrcpy-noconsole.vbs`: start without a terminal (but you won't see any error - message). - -_Avoid double-clicking on `scrcpy.exe` directly: on error, the terminal would -close immediately and you won't have time to read any error message (this -executable is intended to be run from the terminal). Use `scrcpy-console.bat` -instead._ - If you plan to always use the same arguments, create a file `myscrcpy.bat` (enable [show file extensions] to avoid confusion) containing your command, For example: @@ -92,9 +80,17 @@ example: scrcpy --prefer-text --turn-screen-off --stay-awake ``` +Add `--pause-on-exit=if-error` if you want the console to remain open when +scrcpy fails: + +```bash +scrcpy --prefer-text --turn-screen-off --stay-awake --pause-on-exit=if-error +``` + [show file extensions]: https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/ -Then just double-click on that file. +Then just double-click on that file to run it. -You could also edit (a copy of) `scrcpy-console.bat` or `scrcpy-noconsole.vbs` -to add some arguments. +To start scrcpy without opening a terminal, double-click `scrcpy-noconsole.vbs` +(note that errors won't be shown). To pass arguments, edit (a copy of) +`scrcpy-noconsole.vbs` add and the desired arguments. diff --git a/release/build_windows.sh b/release/build_windows.sh index c83d2e31..eb821a95 100755 --- a/release/build_windows.sh +++ b/release/build_windows.sh @@ -45,7 +45,6 @@ ninja -C "$WINXX_BUILD_DIR" # Group intermediate outputs into a 'dist' directory mkdir -p "$WINXX_BUILD_DIR/dist" cp "$WINXX_BUILD_DIR"/app/scrcpy.exe "$WINXX_BUILD_DIR/dist/" -cp app/data/scrcpy-console.bat "$WINXX_BUILD_DIR/dist/" cp app/data/scrcpy-noconsole.vbs "$WINXX_BUILD_DIR/dist/" cp app/data/icon.png "$WINXX_BUILD_DIR/dist/" cp app/data/open_a_terminal_here.bat "$WINXX_BUILD_DIR/dist/"