Repository: pyinstaller/pyinstaller

Issue:
The --splash --onefile must with "VCRUNTIME140.dll"
The --splash --onefile is work good on my computer, but the .exe file must run with VCRUNTIME140.dll on other computer. something wrong maybe.


Discussion:
> something wrong maybe.

Hmm, there actually is. Good job narrowing it down to missing `vcruntime140.dll`!

The problem is that `vcruntime140.dll` is required by the `tcl86t.dll` and `tk86t.dll` that are used for the splash screen. In `onefile` mode, the splash screen is shown before the embedded archive is fully unpacked, after the files declared as splash screen dependencies/requirements are extracted. But as `vcruntime140.dll` is not listed there, we are trying to load Tcl/Tk shared libraries without having extracted the embedded  `vcruntime140.dll`. Therefore, splash screen initialization needs a system-wide copy and fails when the `vcruntime140.dll` DLL is not installed on the target system.

So we need to add binary dependencies of Tcl/Tk shared libs to list of splash screen requirements so that they get extracted before we try to initialize the splash screen.
Glad to have found this thread - having the same problem.
I'm developing on a Winx64, using Python 3.8x32 (portabillity) and have the same issue as above.
I did find that adding the vcruntime140.dll to my inno setup script seems to fix it across target platforms, but it's kind of a janky way of fixing it, stuffing MS DLL files and stuff. But it does work!

Resolving patch:
diff --git a/PyInstaller/building/splash.py b/PyInstaller/building/splash.py
--- a/PyInstaller/building/splash.py
+++ b/PyInstaller/building/splash.py
@@ -18,7 +18,7 @@
 from PyInstaller.building import splash_templates
 from PyInstaller.building.datastruct import TOC, Target
 from PyInstaller.building.utils import _check_guts_eq, _check_guts_toc, misc
-from PyInstaller.compat import is_darwin
+from PyInstaller.compat import is_darwin, is_win, is_cygwin
 from PyInstaller.utils.hooks import exec_statement
 from PyInstaller.utils.hooks.tcl_tk import (TK_ROOTNAME, collect_tcl_tk_files, find_tcl_tk_shared_libs)
 
@@ -218,6 +218,24 @@ def __init__(self, image_file, binaries, datas, **kwargs):
             # true.
             self.binaries.extend(toc for toc in tcltk_tree if toc[0] in self.splash_requirements)
 
+        # Handle extra requirements of Tcl/Tk shared libraries (e.g., vcruntime140.dll on Windows - see issue #6284).
+        # These need to be added to splash requirements, so they are extracted into the initial runtime directory in
+        # order to make onefile builds work.
+        #
+        # The really proper way to implement this would be to perform full dependency analysis on self.tcl_lib[0] and
+        # self.tk_lib[0], and ensure that those dependencies are collected and added to splash requirements. This
+        # would, for example, ensure that on Linux, dependent X libraries are collected, just as if the frozen app
+        # itself was using tkinter. On the other hand, collecting all the extra shared libraries on Linux is currently
+        # futile anyway, because the bootloader's parent process would need to set LD_LIBRARY_PATH to the initial
+        # runtime directory to actually have them loaded (and that requires process to be restarted to take effect).
+        #
+        # So for now, we only deal with this on Windows, in a quick'n'dirty work-around way, by assuming that
+        # vcruntime140.dll is already collected as dependency of some other shared library (e.g., the python shared
+        # library).
+        if is_win or is_cygwin:
+            EXTRA_REQUIREMENTS = {'vcruntime140.dll'}
+            self.splash_requirements.update([name for name, *_ in binaries if name.lower() in EXTRA_REQUIREMENTS])
+
         # Check if all requirements were found.
         fnames = [toc[0] for toc in (binaries + datas + self.binaries)]
 


Test patch: