Closed SaranSundar closed 5 years ago
A quick guess is that you need to include Microsoft.Toolkit.Forms.UI.Controls.WebView.dll (and probably Microsoft.Toolkit.Forms.UI.Controls.WebView.LICENSE.md for licensing reasons) in your exe. In other words, it uses EdgeHTML in development version, but reverts to MSHTML in bundled version as it cannot find this dll.
Ok so I tried this
pyinstaller -w -F --add-data "templates;templates" --add-data "static;static" --add-data "WebBrowserInterop.x86.dll;./" --add-data "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;./" --add-data "Microsoft.Toolkit.Forms.UI.Controls.WebView.LICENSE.md;./" --onefile -y flair.py
This is the output...
169 INFO: checking Analysis
170 INFO: Building Analysis because Analysis-00.toc is non existent
170 INFO: Initializing module dependency graph...
175 INFO: Initializing module graph hooks...
179 INFO: Analyzing base_library.zip ...
4535 INFO: running Analysis Analysis-00.toc
4539 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
required by c:\users\saran\appdata\local\programs\python\python37-32\python.exe
5711 INFO: Caching module hooks...
5718 INFO: Analyzing C:\Users\saran\Documents\PythonProjects\Flair\flair.py
6433 INFO: Processing pre-find module path hook distutils
6490 INFO: Processing pre-find module path hook site
6491 INFO: site: retargeting to fake-dir 'c:\\users\\saran\\appdata\\local\\programs\\python\\python37-32\\lib\\site-packages\\PyInstaller\\fake-modules'
11221 INFO: Loading module hooks...
11222 INFO: Loading module hook "hook-clr.py"...
11225 INFO: Loading module hook "hook-distutils.py"...
11228 INFO: Loading module hook "hook-encodings.py"...
11395 INFO: Loading module hook "hook-jinja2.py"...
11422 INFO: Loading module hook "hook-pkg_resources.py"...
12227 INFO: Processing pre-safe import module hook win32com
12344 INFO: Loading module hook "hook-pydoc.py"...
12345 INFO: Loading module hook "hook-pythoncom.py"...
12843 INFO: Loading module hook "hook-pywintypes.py"...
13450 INFO: Loading module hook "hook-sysconfig.py"...
13452 INFO: Loading module hook "hook-webview.py"...
13456 INFO: Loading module hook "hook-win32com.py"...
14490 INFO: Loading module hook "hook-xml.dom.domreg.py"...
14492 INFO: Loading module hook "hook-xml.py"...
14584 INFO: Looking for ctypes DLLs
14691 INFO: Analyzing run-time hooks ...
14702 INFO: Including run-time hook 'pyi_rth_multiprocessing.py'
14710 INFO: Including run-time hook 'pyi_rth_pkgres.py'
14712 INFO: Including run-time hook 'pyi_rth_win32comgenpy.py'
14742 INFO: Looking for dynamic libraries
18326 WARNING: lib not found: python36.dll dependency of c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\cefpython3\cefpython_py36.pyd
18576 WARNING: lib not found: python35.dll dependency of c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\cefpython3\cefpython_py35.pyd
18629 WARNING: lib not found: python34.dll dependency of c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\cefpython3\cefpython_py34.pyd
18690 WARNING: lib not found: python27.dll dependency of c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\cefpython3\cefpython_py27.pyd
18738 WARNING: lib not found: MSVCR90.dll dependency of c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\cefpython3\cefpython_py27.pyd
20989 WARNING: lib not found: MSVCR90.dll dependency of c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\cefpython3\MSVCP90.dll
20998 INFO: Looking for eggs
20998 INFO: Using Python library c:\users\saran\appdata\local\programs\python\python37-32\python37.dll
20999 INFO: Found binding redirects:
[]
21017 INFO: Warnings written to C:\Users\saran\Documents\PythonProjects\Flair\build\flair\warn-flair.txt
21169 INFO: Graph cross-reference written to C:\Users\saran\Documents\PythonProjects\Flair\build\flair\xref-flair.html
21223 INFO: Appending 'datas' from .spec
21231 INFO: checking PYZ
21231 INFO: Building PYZ because PYZ-00.toc is non existent
21231 INFO: Building PYZ (ZlibArchive) C:\Users\saran\Documents\PythonProjects\Flair\build\flair\PYZ-00.pyz
23185 INFO: Building PYZ (ZlibArchive) C:\Users\saran\Documents\PythonProjects\Flair\build\flair\PYZ-00.pyz completed successfully.
23227 INFO: checking PKG
23229 INFO: Building PKG because PKG-00.toc is non existent
23230 INFO: Building PKG (CArchive) PKG-00.pkg
37724 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
37740 INFO: Bootloader c:\users\saran\appdata\local\programs\python\python37-32\lib\site-packages\PyInstaller\bootloader\Windows-32bit\runw.exe
37740 INFO: checking EXE
37740 INFO: Building EXE because EXE-00.toc is non existent
37741 INFO: Building EXE from EXE-00.toc
37741 INFO: Appending archive to EXE C:\Users\saran\Documents\PythonProjects\Flair\dist\flair.exe
38073 INFO: Building EXE from EXE-00.toc completed successfully.
But unfortunately the exe it makes still looks the same where the top part is cut of for some reason.
Could you get navigator.userAgent printed in both cases to see what renderer is used?
Another thing is if you are indeed using EdgeHTML you can attach Edge debugger to inspect your layout. See https://pywebview.flowrl.com/guide/debugging.html
So this first user agent is when I run my code locally in pycharm and the next is when I run my exe.
User agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362
Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko
The debug flag has little effect on Windows. To debug EdgeHTML you have to install a separate tool. Read documentation.
I did, I got the https://www.microsoft.com/en-us/p/microsoft-edge-devtools-preview/9mzbfrmz0mnj?activetab=pivot:overviewtab. But that only works when you run the app locally, when I run it as an exe the tool doesn't detect the app on localhost. And it is reverting from Edge HTML to MS HTML like you said based on the user agents that were displayed. But I included the dll and the licenses. Any idea what else I should try?
Is there anything else I can try? @r0x0r
This was rather funky. System.Environment.OSVersion
returns Windows 8.1 if the exe manifest does not explicitly state that it is compatible with Windows 10 🤯 Even though pyinstaller creates a correct manifest, but its info gets ignored for some reason.
Anyhow I have changed version detection so it should be more robust now. The change is in master.
@r0x0r So your saying if I run the pyinstaller command on windows now with the latest pywebview everything should work in the exe?
This command down below? Also do you know why it only works with relative paths for me and not absolute paths like to where the pywebview stores it in the c drive?
pyinstaller -w -F --add-data "templates;templates" --add-data "static;static" --add-data "WebBrowserInterop.x86.dll;./" --add-data "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;./" --add-data "Microsoft.Toolkit.Forms.UI.Controls.WebView.LICENSE.md;./" --onefile -y flair.py
Yes, but you have to install the version from master first.
Ok thanks I will try that with the latest master branch in around two hours and let you know if it works. But any idea on the absolute path issue?
Sorry no idea. This is rather a pyinstaller issue, than a pywebview one.
I see thats fine then thanks. Also I've been working on a framework called Flair for sometime now that would replace electron JS and is 90% more memory efficient, before I was just using a chrome window, is it ok if i use pywebview in my framework?
@r0x0r Ok so its working and also not working. I updated the winforms.py with the changes you pushed. The generated exe only works if I dont use the -w option for pyinstaller. But this means that now the app opens through command line instead of just being its own window. Do you have any idea why it doesnt work with the -w option, it just makes cursor blue circle for a bit and then does nothing no app opens. Only in console without -w does the app open.
I have a feeling the flask server is taking a long time to start, because even in console mode i can see it wait a few seconds for flask to start before the app opens. so my guess is without console it kills itself before the flask starts im not sure. But it worked before the winform changes were made so that shouldnt be the case.
It is the same issue as https://github.com/r0x0r/pywebview/issues/347 It seems to occur semi sporadically and I got it reproduced with 2.4 as well. It looks like a Pyinstaller issue to me. If you with to debug it, one way to do it would be to reroute stdout / stdout to a file and check if it produces any output when frozen with no console.
Hmm his solution was to use a clean install of windows 10, but my windows 10 is a clean install that I used just to get the exe working since I normally use mac os. I'll try getting any output I can of the exe.
Do you have all the four dlls bundled with your exe? Python.Runtime.dll WebBrowserInterop.x86.dll WebBrowserInterop.x64.dll Microsoft.Toolkit.Forms.UI.Controls.WebView.dll
No, the command I use is
pyinstaller -w -F --add-data "templates;templates" --add-data "static;static" --add-data "WebBrowserInterop.x86.dll;./" --add-data "WebBrowserInterop.x64.dll;./" --add-data "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;./" --add-data "Microsoft.Toolkit.Forms.UI.Controls.WebView.LICENSE.md;./" --onefile -y flair.py
I thought the only thing you need to bundle is is those 3 dlls and the license. Where does the Python.runtime.dll come from, I never bundled it before when I make the exe work or in console mode?
Also according to the redirected stdout, the flask server starts fine. I think the problem is in webview.start(). I think it fails to create the window popup and then the code exits.
Python.Runtime.dll is required by pythonnet, but it should be bundled automatically by pyinstaller
I'm pretty sure the problem is the start method isn't working when there's no console so I'll try to debug that and see if I can find something.
@r0x0r Yah I noticed something else interesting. Pywebview 3.0 doesnt work on mac os if you launch through an IDE like PyCharms. As in it creates a window that doesnt popup, no app icon is shown in the dock, and you can only see the window in the background but you cant click on it or it goes away. BUT if run the python code in the terminal pywebview works fine. I'm thinking there must be some issue in the start method of how the gui launches but not sure yet.
https://upload.disroot.org/r/2dXObWgx#BQXbu8yEikQl0HcgWsewJOuT5s3QWI7K0MVnOZd+dkI=
I posted the video showing the bug above.
@r0x0r @shivaprsdv Ok I finally managed to solve this issue after days of debugging and I also solved the issue of it not working in the --no-console version or the -w paramater of pyinstaller. The culprit was a method inside the winforms.py
def _allow_localhost(): output = check_output('checknetisolation LoopbackExempt -s')
if 'cw5n1h2txyewy' not in str(output):
windll.shell32.ShellExecuteW(None, 'runas', 'checknetisolation', 'LoopbackExempt -a -n=\"Microsoft.Win32WebViewHost_cw5n1h2txyewy\"', None, 1)
check_output('checknetisolation LoopbackExempt -s') this causes it to crash for various reasons.
You need to enable it
2) In no console mode this command doesnt work regardless.
My solution was to comment out the code in this method, and then everything works fine now I can create the exe and launch it and my react app looks fine.
What does this method do and is it important to keep in the future?
@SaranSundar Excellent work! EdgeHTML does not support opening localhost URLs for security reasons (shrug). LoopbackExempt needs to be added in order to allow localhost URLs. To make matters even more complicated, LoopbackExempt requires administrator rights. This is an unfortunate feature and _allow_localhost
is rather a clutch to make it work. Too bad pyinstaller does not work with it.
Does it fail at the check_output
or runas
stage? I think this is a pyinstaller issue, but maybe some workaround could be made at the pywebview end. Could you raise an issue in the pyinstaller repo?
Could you try pyinstaller's --uac-admin
option if it solves the problem?
Thanks. It fails at the check_output, with the -w parameter for window and works without it when it uses the console. What's strange is if I just comment out the code in allow local host, it won't prompt me for admin rights and it does load my local host url I'm serving with flask. Do you want me to try the uac admin with the commented out allow local host or with it as it originally was?
This command must be run only once per machine. check_outout just checks whether it was set. Please try uac admin with the original code.
uac admin doesn't make it work with the original code. Can you choose browser of choice in pywebview like perhaps chrome instead of edge?
I think I found the cause of this issue, namely subprocess.check_output
fails under pyinstaller. I replaced it with os.open
. Could you test the version from master?
When i pulled the latest master locally, I cant even run the code in my editor anymore.
Traceback (most recent call last):
File "C:\Program Files\JetBrains\PyCharm 2019.1.3\helpers\pydev\pydevd.py", line 1758, in
The path is fine and it exists but still throws an error.
This looks like a Windows 10 security issue. You have to unblock the dll on your machine by right clicking it, selecting Properties and checking Unblock.
Ok I can generate the exe now but it still crashes at that point I think.
Ok, another try. I copied a recipe from https://github.com/pyinstaller/pyinstaller/wiki/Recipe-subprocess and producing an exe with no console works at least on my machine. Can you verify it?
Ok everything works now perfect! One thing I'm wondering though is why do we need to set the dll property to unblock, because 2 or 3 commits ago I never had to do that for everything to work, so what changed?
This is a Windows security feature for downloaded DLLs. No idea why it was triggered in this case.
I tried freezing one my of apps made with Flask and got it working only when I redirected stdout to a separate stream or a file. ie
if __name__ == '__main__':
from io import StringIO
stream = StringIO()
with redirect_stdout(stream):
# app entry point
Thats interesting I never had to do anything like that for my flask apps. Your saying your exe only ran when you redirected the output for print statements?
Yep, it does not work otherwise. My setup
Package Version
------------------ ---------
altgraph 0.16.1
atomicwrites 1.3.0
attrs 19.1.0
Click 7.0
colorama 0.4.1
Flask 1.1.1
future 0.17.1
importlib-metadata 0.18
itsdangerous 1.1.0
Jinja2 2.10.1
MarkupSafe 1.1.1
more-itertools 7.2.0
packaging 19.0
pathlib2 2.3.4
pefile 2019.4.18
pip 19.2
pluggy 0.12.0
py 1.8.0
PyInstaller 3.5
pyparsing 2.4.1
pytest 5.0.1
pythonnet 2.4.0
pywebview 3.0
pywin32-ctypes 0.2.0
setuptools 41.0.1
six 1.12.0
wcwidth 0.1.7
Werkzeug 0.15.5
wheel 0.33.4
zipp 0.5.2
Interesting, I created a framework called Flair and it's essentially a 90% more effective electron js using python and flask in the backend instead of node. Now that the issue with pywebview is resolved for me I'll release it soon with documentation on how to use and build for windows and mac. If you want you can test a flair app since it's a flask app but doesn't require the redirect your using. Also the unblocking of dll only happened 1 or 2 times for me but hasn't happened on a partners laptop so its somewhat unpredictable as well I suppose.
@r0x0r I think this issue is completely resolved now so I'll go ahead and close it. Thanks so much for your help!
Specification
Description
I got packaging to work for my React app on Mac and Windows. The only weird thing is on windows when I run the exe the height in the page seems to be missing, this is best explained through the photos. It works fine if i run my code In pycharms, it's only after packaging as exe do I see this weird bug.
Run from PyCharm on windows and what it looks like on mac: https://i.imgur.com/sJZCegr.png After packaging: https://i.imgur.com/6kEUfTT.png
To recreate this, you can make a new react app with
npx create-react-app
, runnpm build
in it, and move the index.html from the build folder to a templates folder and the rest to the static folder.And I use this command to package
pyinstaller -w -F --add-data "templates;templates" --add-data "static;static" --add-data "WebBrowserInterop.x86.dll;./" --onefile -y flair.py
It's also weird that its using x86 since I'm pretty sure I have the 64 bit of python. And also when I used the full path like C:\Users\saran\AppData\Local\Programs\Python\Python37-32\Lib\site-packages\webview\lib\WebBrowserInterop.x86.dll It never worked for me. Only when I copied it into local folder did it work.
Practicalities
[X] I am willing to work on this issue myself.
[ ] I am prepared to support this issue financially.