aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsepro <4618135+seproDev@users.noreply.github.com>2024-02-24 12:58:03 +0100
committerGitHub <noreply@github.com>2024-02-24 12:58:03 +0100
commit6a6cdcd1824a14e3b336332c8f31f65497b8c4b8 (patch)
tree8728443856cc8193725c94bdf1ad25b8128c7a05
parent998dffb5a2343ec709b3d6bbf2bf019649080239 (diff)
[core] Warn user when not launching through shell on Windows (#9250)
Authored by: seproDev, Grub4K Co-authored-by: Simon Sawicki <contact@grub4k.xyz>
-rw-r--r--yt_dlp/__init__.py25
-rw-r--r--yt_dlp/options.py7
2 files changed, 28 insertions, 4 deletions
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
index 57a487157..4380b888d 100644
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -14,7 +14,7 @@ import os
import re
import traceback
-from .compat import compat_shlex_quote
+from .compat import compat_os_name, compat_shlex_quote
from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
from .downloader.external import get_external_downloader
from .extractor import list_extractor_classes
@@ -984,7 +984,28 @@ def _real_main(argv=None):
if pre_process:
return ydl._download_retcode
- ydl.warn_if_short_id(sys.argv[1:] if argv is None else argv)
+ args = sys.argv[1:] if argv is None else argv
+ ydl.warn_if_short_id(args)
+
+ # Show a useful error message and wait for keypress if not launched from shell on Windows
+ if not args and compat_os_name == 'nt' and getattr(sys, 'frozen', False):
+ import ctypes.wintypes
+ import msvcrt
+
+ kernel32 = ctypes.WinDLL('Kernel32')
+
+ buffer = (1 * ctypes.wintypes.DWORD)()
+ attached_processes = kernel32.GetConsoleProcessList(buffer, 1)
+ # If we only have a single process attached, then the executable was double clicked
+ # When using `pyinstaller` with `--onefile`, two processes get attached
+ is_onefile = hasattr(sys, '_MEIPASS') and os.path.basename(sys._MEIPASS).startswith('_MEI')
+ if attached_processes == 1 or is_onefile and attached_processes == 2:
+ print(parser._generate_error_message(
+ 'Do not double-click the executable, instead call it from a command line.\n'
+ 'Please read the README for further information on how to use yt-dlp: '
+ 'https://github.com/yt-dlp/yt-dlp#readme'))
+ msvcrt.getch()
+ _exit(2)
parser.error(
'You must provide at least one URL.\n'
'Type yt-dlp --help to see a list of all options.')
diff --git a/yt_dlp/options.py b/yt_dlp/options.py
index ab4986515..14b030cfb 100644
--- a/yt_dlp/options.py
+++ b/yt_dlp/options.py
@@ -196,9 +196,12 @@ class _YoutubeDLOptionParser(optparse.OptionParser):
raise
return self.check_values(self.values, self.largs)
- def error(self, msg):
+ def _generate_error_message(self, msg):
msg = f'{self.get_prog_name()}: error: {str(msg).strip()}\n'
- raise optparse.OptParseError(f'{self.get_usage()}\n{msg}' if self.usage else msg)
+ return f'{self.get_usage()}\n{msg}' if self.usage else msg
+
+ def error(self, msg):
+ raise optparse.OptParseError(self._generate_error_message(msg))
def _get_args(self, args):
return sys.argv[1:] if args is None else list(args)