1

I'm trying to run a Windows executable inside my application written in Python using PyQt5. I'm fairly new to using PyQt5 but trying.

The problem I'm facing is actually getting the EXE in question to run within my applications Frame, Window or QWidget.

At the moment I don't need to send or get responses/results to and from the Windows executable, I only need the ability to show it within my application.

class MyWindow(QWidget):

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

     self.initUI()

   def initUI(self):
     # create a process
     exePath = "C:\\Windows\\system32\\calc.exe"
     # subprocess.Popen(exePath)
     os.system(exePath)
     hwnd = win32gui.FindWindow(0,"Calculator")
     print(hwnd)
     time.sleep(0.05)
     window = QtGui.QWindow.fromWinId(hwnd)

     self.createWindowContainer(window, self)
     self.setGeometry(500, 500, 450, 400)
     self.setWindowTitle('File dialog')
     self.show()

def main():
  app = QApplication(sys.argv)
  w = MyWindow()
  sys.exit(app.exec_())


if __name__ == '__main__':
    main()

What I get from the following Code is this:

Screenshot of running app

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • What did you get from `print(hwnd)` ? – Ben Voigt Aug 26 '20 at 18:45
  • Note that your terminology suggests that you do not understand what is going on here. The executable will never run "inside" your application -- you are spawning a separate process. That process is creating a window (but could create zero or multiple) which have thread affinity to a thread in that process. You are trying to change the created window's attributes from top-level (no parent) to becoming a child of the window you created in your application. This is an operation on a window not on an executable. – Ben Voigt Aug 26 '20 at 18:48
  • Also your sleep is in the wrong place, you should allow time for the process spawn and window creation before you go looking for the window. – Ben Voigt Aug 26 '20 at 18:49
  • Finally, `FindWindow` only works on windows managed by `USER32.DLL`. If you have a console window or a modern UI application, you'll need to approach that totally differently. – Ben Voigt Aug 26 '20 at 18:50
  • @BenVoigt Thanks for the insight Ben. Do you perhaps have an idea how I could accomplish this? – Caylem Harris Aug 26 '20 at 19:28
  • You still haven't answered my first question. What did you get from `print(hwnd)`? – Ben Voigt Aug 26 '20 at 21:44
  • @BenVoigt I got the hwnd = 197964? It changes every time I run the application. – Caylem Harris Aug 27 '20 at 05:15
  • Ok, that looks like FindWindow is succeeding (you are checking after the window is created, and the target is a ISER32 window not a modern UI) – Ben Voigt Aug 27 '20 at 16:52
  • @BenVoigt Hi Ben, do you thinks its viable for me to look into how to implement the USER32.dll and perhaps how WinUI 3 (Modern UI) can integrate with Python? – Caylem Harris Aug 31 '20 at 13:26

1 Answers1

0

Sorry, I don't know if I understood you correctly, but I suggest trying this:

import sys
import subprocess
import threading
import time
import win32gui
from PyQt5.QtCore    import Qt
from PyQt5.QtGui     import QWindow, QPixmap
from PyQt5.QtWidgets import (QWidget, QApplication, QVBoxLayout,
                             QGridLayout, QMainWindow, QLabel) 


class Example(QMainWindow):
    def __init__(self):
        super().__init__()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        
        self.widget = QWidget()
        self.widget.setFixedSize(230, 280)
        self.widget.setStyleSheet("background-color: yellow;")
        self.label = QLabel(self)
        self.label.setPixmap(
            QPixmap('images/splash_.jpg').scaled(self.size().width()/2, self.size().height())
        )
        
        self.grid_layout = QGridLayout(self.central_widget)
        self.grid_layout.addWidget(self.widget, 0, 0, 2, 1)
        
        self.v_layout = QVBoxLayout(self.widget)
        self.initUI()
        self.grid_layout.addWidget(self.label, 0, 1, 1, 1) 
 
    def initUI(self):
        t = threading.Thread(target=self.runExe)
        t.start()
        #                                                 Calculator
        hwnd1 = win32gui.FindWindowEx(0, 0, "CalcFrame", "Калькулятор")
        start = time.time()
        while hwnd1 == 0:
            time.sleep(0.01)
            #                                                 Calculator 
            hwnd1 = win32gui.FindWindowEx(0, 0, "CalcFrame", "Калькулятор")
            end = time.time()
            if end - start > 5:
                return
        window = QWindow.fromWinId(hwnd1)
        widget = self.createWindowContainer(window, self.central_widget)
        self.v_layout.addWidget(widget)
 
    @staticmethod
    def runExe():
        exePath = "C:/Windows/system32/calc.exe"
        subprocess.Popen(exePath)

 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    ex.resize(550, 400)
    ex.show()
    sys.exit(app.exec_())

enter image description here

S. Nick
  • 12,879
  • 8
  • 25
  • 33