Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Console window pops up when using pythonw #31

Closed
kynax opened this issue Feb 24, 2022 · 6 comments
Closed

Console window pops up when using pythonw #31

kynax opened this issue Feb 24, 2022 · 6 comments

Comments

@kynax
Copy link

kynax commented Feb 24, 2022

When using pythonw.exe (instead of python.exe) to make a call, a console window pops up to run the server32-windows.exe process.

You can recreate the behavior using the attached code.
msl_console.txt

When running under python.exe (python.exe msl_console.txt), you get the expected result of the console getting the path, then time twice.

When running under pythonw.exe (pythonw.exe msl_console.txt), the expected result should be that nothing is printed to the active console.
The observed behavior is that a console window pops up and flashes a few times to run the server32-windows.exe process.

This is an issue when developping GUI apps since the users will be bombarded with console windows when using the app
msl_console
.

@jborbely
Copy link
Contributor

Could you try experimenting with different STARTUPINFO flags to get the desired result.

Modify this line in your ..\site-packages\msl\loadlib\client64.py file to be

        si = None
        if sys.executable.endswith('pythonw.exe'):
            si = subprocess.STARTUPINFO()
            si.dwFlags = subprocess.STARTF_USESHOWWINDOW
            si.wShowWindow = subprocess.SW_HIDE
        self._proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, startupinfo=si)

The dwFlags and wShowWindow values that I used will stop the console window from popping up, but there is still an icon flashing in the taskbar.

@kynax
Copy link
Author

kynax commented Feb 28, 2022

I think this is a good start, but it doesn't seem to have the desired effect in my environment.

I'm actually running a pyQT5 app so I guess that the example that I provided earlier isn't the best, since you'd normally only use pythonw.exe if you actually initialize a GUI yourself.

Here is another more completed recreation of what the call might look like on my end.
You might need to 'pip install PyQt5' to run it.
msl_qt5.txt

@jborbely
Copy link
Contributor

What is the desired effect that you are still hoping for that has not already been achieved with the STARTUPINFO change? Is it that the console that you execute the pythonw.exe command flashes for about 2 seconds?

For example, running the following script with pythonw.exe qt5_example.py causes the console to initially flash for about 2 seconds, when the self._k = Kernel64() line is executed, but afterwards I cannot tell the difference between running the script with python.exe versus pythonw.exe.

# qt5_example.py

import sys
from PyQt5.QtWidgets import *
from msl.examples.loadlib import Kernel64

class Window(QWidget):

    def __init__(self):
        super(Window, self).__init__()

        self._k = Kernel64()

        button_alert = QPushButton('Alert')
        button_alert.clicked.connect(self.on_alert_clicked)

        button_update = QPushButton('Get time')
        button_update.clicked.connect(self.on_update_clicked)

        self._label = QLabel()

        layout = QVBoxLayout()
        layout.addWidget(button_alert)
        layout.addWidget(button_update)
        layout.addWidget(self._label)
        self.setLayout(layout)

    def on_alert_clicked(self):
        alert = QMessageBox()
        alert.setText(sys.executable + '\n' + str(self._k.get_local_time()))
        alert.exec_()

    def on_update_clicked(self):
        self._label.setText(f'<html>The current time is:<br>'
                            f'<b>{self._k.get_local_time()}</b></html>')

    def closeEvent(self, event):
        event.accept()
        self._k.shutdown_server32()


if __name__ == '__main__':
    app = QApplication([])
    window = Window()
    window.show()
    sys.exit(app.exec_())

I ran your pythonw.exe msl_qt5.txt example, but that too does not create a pop up console.

@kynax
Copy link
Author

kynax commented Mar 1, 2022

Your comment helped me diagnose the issue further.
It is indeed the flashing window that I was observing.
Knowing this, I made a screen recording a found that it was the 'netstat' process flashing multiple times.

It's caused by utils.wait_for_server calling is_port_in_use in a loop until the server is up. On slower machines, this might take a few seconds.

I fixed it by adding the creationflags parameter to the Popen call in is_port_in_use:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW)

This parameter should probably be added to all Popen calls since the expected behavior of the whole package is to run silently in the background. I have tested replacing the call in client64.py too with success, instead of using the STARTUPINFO construct.

@jborbely
Copy link
Contributor

jborbely commented Mar 1, 2022

Great! Thanks for tracking down a fix to this issue.

I have pushed your suggested fix in 784321d (with a slight modification to also support a non-Windows OS and Python < 3.7).

Could you please upgrade the package from the main branch to check that this issue will be resolved in the next release and then let me know the result. To install from main you can run

python -m pip install -U https://github.com/MSLNZ/msl-loadlib/archive/main.zip

@kynax
Copy link
Author

kynax commented Mar 2, 2022

I installed from the main branch and can confirm that it fixes the issue.

Thank you!

@kynax kynax closed this as completed Mar 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants