Repository: pyinstaller/pyinstaller

Issue:
getting something error like this " %1 is not a valid Win32 application. (Error code 193) "
<!--
Welcome to the PyInstaller issue tracker! Before creating an issue, please heed the following:

1. This tracker should only be used to report bugs and request features / enhancements to PyInstaller
    - For questions and general support, use the mailing list, see
	  <http://www.pyinstaller.org/support.html#mailing-list>
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
   the original discussion.
3. When making a bug report, make sure you provide all required information. The easier it is for
   maintainers to reproduce, the faster it'll be fixed.
-->

+++ ONLY TEXT +++ DO NOT POST IMAGES +++

## Description of the issue

## Context information (for bug reports)

* Output of `pyinstaller --version`: ```(paste here)```
* Version of Python: e.g. 3.7
* Platform: e.g GNU/Linux (distribution), Windows (language settings), OS X, conda, FreeBSD
* Did you also try this on another platform? Does it work there?


* try the latest development version, using the following command:

```shell
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
```

* follow *all* the instructions in our "If Things Go Wrong" Guide
  (https://github.com/pyinstaller/pyinstaller/wiki/If-Things-Go-Wrong) and

### Make sure [everything is packaged correctly](https://github.com/pyinstaller/pyinstaller/wiki/How-to-Report-Bugs#make-sure-everything-is-packaged-correctly)

  * [x] start with clean installation
  * [x] use the latest development version
  * [x] Run your frozen program **from a command window (shell)** — instead of double-clicking on it
  * [x] Package your program in **--onedir mode**
  * [x] Package **without UPX**, say: use the option `--noupx` or set `upx=False` in your .spec-file
  * [x] Repackage you application in **verbose/debug mode**. For this, pass the option `--debug` to `pyi-makespec` or `pyinstaller` or use `EXE(..., debug=1, ...)` in your .spec file.


### A minimal example program which shows the error

```
(paste text here)
“Minimal“ means: remove everything from your code which is not relevant for this bug,
esp. don't use external programs, remote requests, etc.
A very good example is https://gist.github.com/ronen/024cdae9ff2d50488438. This one helped
us reproducing and fixing a quite complex problem within approx 1 hour.
```

### Stacktrace / full error message

```
53243 INFO: Warnings written to D:\NS Word\build\main_complete\warn-main_complete.txt
53468 INFO: Graph cross-reference written to D:\NS Word\build\main_complete\xref-main_complete.html
53587 INFO: checking PYZ
53624 INFO: Building PYZ because PYZ-00.toc is non existent
53639 INFO: Building PYZ (ZlibArchive) D:\NS Word\build\main_complete\PYZ-00.pyz
57333 INFO: Building PYZ (ZlibArchive) D:\NS Word\build\main_complete\PYZ-00.pyz completed successfully.
57528 INFO: checking PKG
57578 INFO: Building PKG because PKG-00.toc is non existent
57591 INFO: Building PKG (CArchive) PKG-00.pkg
109557 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
109587 INFO: Bootloader c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
109590 INFO: checking EXE
109591 INFO: Building EXE because EXE-00.toc is non existent
109592 INFO: Building EXE from EXE-00.toc
109915 INFO: Copying icons from D:\NS Word\google_docs.png
Unable to load icon file D:\NS Word\google_docs.png
    %1 is not a valid Win32 application. (Error code 193)
```

Please also see <https://github.com/pyinstaller/pyinstaller/wiki/How-to-Report-Bugs>
for more about what would use to solve the issue.



Discussion:
Ah, that. What it's really trying to say is:

*I can't use PNG images as icons on Windows. I can use a .ico file or copy the .ico from another exe file that already has an icon. Please convert your PNG to .ico then try again.*

Unfortunately, it verifies that your PNG is not a .ico but then just assumes that it is a valid EXE (which of course it isn't - it's a picture) and points Windows API at it which raises the cryptic error:

> Unable to load icon file D:\NS Word\google_docs.png
    %1 is not a valid Win32 application. (Error code 193)

I meant to change that yonks ago but never did...

Resolving patch:
diff --git a/PyInstaller/utils/win32/icon.py b/PyInstaller/utils/win32/icon.py
--- a/PyInstaller/utils/win32/icon.py
+++ b/PyInstaller/utils/win32/icon.py
@@ -224,6 +224,18 @@ def splitter(s):
     else:
         logger.info("Copying icons from %s", srcpath)
 
+    # Bail out quickly if the input is invalid. Letting images in the wrong
+    # format be passed to Window's API gives very cryptic error messages as
+    # it's generally unclear why PyInstaller would treat an image file as an
+    # executable.
+    if srcext != ".exe":
+        raise ValueError(
+            f"Received icon path '{srcpath}' which exists but is not in the "
+            f"correct format. On Windows, only '.ico' images or other "
+            f"'.exe' files may be used as icons. Please convert your "
+            f"'{srcext}' file to a '.ico' then try again."
+        )
+
     try:
         # Attempt to load the .ico or .exe containing the icon into memory
         # using the same mechanism as if it were a DLL. If this fails for


Test patch:
diff --git a/tests/functional/data/invalid_icon/pyi_icon.png b/tests/functional/data/invalid_icon/pyi_icon.png
new file mode 100644
Binary files /dev/null and b/tests/functional/data/invalid_icon/pyi_icon.png differ
diff --git a/tests/functional/test_basic.py b/tests/functional/test_basic.py
--- a/tests/functional/test_basic.py
+++ b/tests/functional/test_basic.py
@@ -15,6 +15,7 @@
 import locale
 import os
 import sys
+import shutil
 
 # Third-party imports
 # -------------------
@@ -380,6 +381,28 @@ def test_set_icon(pyi_builder, data_dir):
     pyi_builder.test_source("print('Hello Python!')", pyi_args=args)
 
 
+@pytest.mark.win32
+def test_invalid_icon(tmpdir, data_dir):
+    """Ensure a sane error message is given if the user provides a PNG or other
+    unsupported format of image."""
+    from PyInstaller import PLATFORM, HOMEPATH
+    from PyInstaller.utils.win32.icon import CopyIcons
+
+    icon = os.path.join(data_dir.strpath, 'pyi_icon.png')
+    bootloader_src = os.path.join(
+        HOMEPATH, 'PyInstaller', 'bootloader', PLATFORM, "run.exe")
+    exe = os.path.join(tmpdir, "run.exe")
+    shutil.copy(bootloader_src,  exe)
+    assert os.path.isfile(icon)
+    assert os.path.isfile(exe)
+
+    with pytest.raises(ValueError,
+                       match="path '.*pyi_icon.png' .* not in the correct "
+                             "format.*"
+                             "convert your '.png' file to a '.ico' .*"):
+        CopyIcons(exe, icon)
+
+
 def test_python_home(pyi_builder):
     pyi_builder.test_script('pyi_python_home.py')