【问题标题】:Running a Windows executable (calc.exe, etc) inside a PyQt Application在 PyQt 应用程序中运行 Windows 可执行文件(calc.exe 等)
【发布时间】:2020-12-15 05:52:10
【问题描述】:

我正在尝试在使用 PyQt5 用 Python 编写的应用程序中运行 Windows 可执行文件。我对使用 PyQt5 还很陌生,但正在尝试。

我面临的问题实际上是让有问题的 EXE 在我的应用程序框架、窗口或 QWidget 中运行。

目前我不需要向 Windows 可执行文件发送或获取响应/结果,我只需要能够在我的应用程序中显示它。

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()

我从以下代码中得到的是:

【问题讨论】:

  • 你从print(hwnd)得到了什么?
  • 请注意,您的术语表明您不了解这里发生的情况。可执行文件永远不会在您的应用程序“内部”运行——您正在生成一个单独的进程。该进程正在创建一个与该进程中的线程具有线程关联性的窗口(但可以创建零个或多个)。您正在尝试将创建的窗口的属性从顶级(无父级)更改为您在应用程序中创建的窗口的子级。这是对窗口的操作,而不是对可执行文件的操作。
  • 另外你的睡眠是在错误的地方,你应该在寻找窗口之前留出时间来产生进程和创建窗口。
  • 最后,FindWindow 只适用于USER32.DLL 管理的窗口。如果您有控制台窗口或现代 UI 应用程序,则需要以完全不同的方式处理。
  • @BenVoigt 感谢本的洞察力。您是否知道我该如何完成这项工作?

标签: python python-3.x windows user-interface pyqt5


【解决方案1】:

对不起,我不知道我是否理解正确,但我建议您试试这个:

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_())

【讨论】:

  • 看起来不错,但仍然得到相同的结果...只是一个问题,您使用的是 Windows 7 还是 Windows 10?不确定操作系统版本是否重要?
  • @CaylemHarris 在 Windows 7 上测试。
  • 似乎 Windows 10 可执行文件的调用方式不同?不确定,需要调查一下吗?谢谢
  • @Snick 如果你找到任何东西,请告诉我?再次感谢;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
相关资源
最近更新 更多