Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. How to create a QIcon from a .exe path?

How to create a QIcon from a .exe path?

Scheduled Pinned Locked Moved Solved Qt for Python
4 Posts 3 Posters 264 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mizmas
    wrote on last edited by
    #1

    Hello, I'm trying to add installed applications and their icons to a QComboBox.

    Below is an example code that anyone can copy and run.

    It successfully retrieves installed applications from the registry, and also the path of their icon if it exists.

    The problem is that QIcon is only created if the application's icon_path is a path with a .ico extension, so if a program's icon_path is retrieved as .exe, a QIcon won't get created.

    You can run the code and compare what paths it prints out to the QIcons that are created in the QComboBox:

    import sys
    import os
    import winreg
    from PyQt6.QtWidgets import QApplication, QComboBox, QMainWindow
    from PyQt6.QtGui import QIcon
    from PyQt6.QtCore import QSize
    
    
    def get_installed_apps_from_registry(registry_path):
        apps = []
        try:
            reg_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0, winreg.KEY_READ)
            for i in range(0, winreg.QueryInfoKey(reg_key)[0]):
                try:
                    subkey_name = winreg.EnumKey(reg_key, i)
                    subkey = winreg.OpenKey(reg_key, subkey_name)
    
                    # Retrieve app name
                    app_name, _ = winreg.QueryValueEx(subkey, "DisplayName")
    
                    # Retrieve app icon path
                    try:
                        icon_path, _ = winreg.QueryValueEx(subkey, "DisplayIcon")
                        icon_path = icon_path.split(",")[0].strip()  # Clean up icon path
                        if not os.path.isfile(icon_path):
                            icon_path = None
                    except FileNotFoundError:
                        icon_path = None
    
                    # Append app name and icon path to the list
                    apps.append({"name": app_name, "icon": icon_path})
                except EnvironmentError:
                    continue
                finally:
                    subkey.Close()
        except EnvironmentError:
            pass
        return apps
    
    
    def list_installed_apps():
        registry_paths = [
            r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
            r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
        ]
        installed_apps = []
        for path in registry_paths:
            installed_apps.extend(get_installed_apps_from_registry(path))
    
        # Remove duplicates and sort
        unique_apps = {app['name']: app for app in installed_apps if app['name']}
        sorted_apps = sorted(unique_apps.values(), key=lambda x: x['name'])
        return sorted_apps
    
    
    def create_icon(icon_path):
        # Create QIcon from path
        if icon_path and os.path.isfile(icon_path):
            return QIcon(icon_path)
        return QIcon()  # Return empty icon if path is invalid
    
    
    class AppComboBox(QMainWindow):
        def __init__(self, apps):
            super().__init__()
            self.setWindowTitle("Installed Applications")
            self.setGeometry(100, 100, 400, 100)
    
            # Create QComboBox
            self.combo = QComboBox(self)
            self.combo.setIconSize(QSize(32, 32))
            self.combo.setGeometry(50, 20, 300, 40)
    
            # Add apps to combo box with icons
            for app in apps:
                icon = create_icon(app['icon'])
                self.combo.addItem(icon, app['name'])
    
    
    def main():
        # Fetch installed applications
        apps = list_installed_apps()
    
        # Print program name and icon path
        for app in apps:
            print(f"Name: {app['name']}")
            print(f"Icon Path: {app['icon']}")
            print("-" * 40)
    
        # Set up the PyQt6 application
        app = QApplication(sys.argv)
        window = AppComboBox(apps)
        window.show()
        sys.exit(app.exec())
    
    
    if __name__ == "__main__":
        main()
    
    
    JonBJ 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      That's because QIcon has no reason to know how to extract a file from an exe binary.
      It's a step you have to implement yourself.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • M Mizmas

        Hello, I'm trying to add installed applications and their icons to a QComboBox.

        Below is an example code that anyone can copy and run.

        It successfully retrieves installed applications from the registry, and also the path of their icon if it exists.

        The problem is that QIcon is only created if the application's icon_path is a path with a .ico extension, so if a program's icon_path is retrieved as .exe, a QIcon won't get created.

        You can run the code and compare what paths it prints out to the QIcons that are created in the QComboBox:

        import sys
        import os
        import winreg
        from PyQt6.QtWidgets import QApplication, QComboBox, QMainWindow
        from PyQt6.QtGui import QIcon
        from PyQt6.QtCore import QSize
        
        
        def get_installed_apps_from_registry(registry_path):
            apps = []
            try:
                reg_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0, winreg.KEY_READ)
                for i in range(0, winreg.QueryInfoKey(reg_key)[0]):
                    try:
                        subkey_name = winreg.EnumKey(reg_key, i)
                        subkey = winreg.OpenKey(reg_key, subkey_name)
        
                        # Retrieve app name
                        app_name, _ = winreg.QueryValueEx(subkey, "DisplayName")
        
                        # Retrieve app icon path
                        try:
                            icon_path, _ = winreg.QueryValueEx(subkey, "DisplayIcon")
                            icon_path = icon_path.split(",")[0].strip()  # Clean up icon path
                            if not os.path.isfile(icon_path):
                                icon_path = None
                        except FileNotFoundError:
                            icon_path = None
        
                        # Append app name and icon path to the list
                        apps.append({"name": app_name, "icon": icon_path})
                    except EnvironmentError:
                        continue
                    finally:
                        subkey.Close()
            except EnvironmentError:
                pass
            return apps
        
        
        def list_installed_apps():
            registry_paths = [
                r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
            ]
            installed_apps = []
            for path in registry_paths:
                installed_apps.extend(get_installed_apps_from_registry(path))
        
            # Remove duplicates and sort
            unique_apps = {app['name']: app for app in installed_apps if app['name']}
            sorted_apps = sorted(unique_apps.values(), key=lambda x: x['name'])
            return sorted_apps
        
        
        def create_icon(icon_path):
            # Create QIcon from path
            if icon_path and os.path.isfile(icon_path):
                return QIcon(icon_path)
            return QIcon()  # Return empty icon if path is invalid
        
        
        class AppComboBox(QMainWindow):
            def __init__(self, apps):
                super().__init__()
                self.setWindowTitle("Installed Applications")
                self.setGeometry(100, 100, 400, 100)
        
                # Create QComboBox
                self.combo = QComboBox(self)
                self.combo.setIconSize(QSize(32, 32))
                self.combo.setGeometry(50, 20, 300, 40)
        
                # Add apps to combo box with icons
                for app in apps:
                    icon = create_icon(app['icon'])
                    self.combo.addItem(icon, app['name'])
        
        
        def main():
            # Fetch installed applications
            apps = list_installed_apps()
        
            # Print program name and icon path
            for app in apps:
                print(f"Name: {app['name']}")
                print(f"Icon Path: {app['icon']}")
                print("-" * 40)
        
            # Set up the PyQt6 application
            app = QApplication(sys.argv)
            window = AppComboBox(apps)
            window.show()
            sys.exit(app.exec())
        
        
        if __name__ == "__main__":
            main()
        
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @Mizmas
        I think https://stackoverflow.com/questions/1616342/best-way-to-extract-ico-from-exe-and-paint-with-pyqt shows how you have to do this. Read each answer carefully, and the little comments, to allow for PyQt6 (or PySide6).

        If you can translate the few lines of https://stackoverflow.com/a/50809652/489865 into PyQt/PySide and it works on an exe that's even simpler.

        M 1 Reply Last reply
        1
        • JonBJ JonB

          @Mizmas
          I think https://stackoverflow.com/questions/1616342/best-way-to-extract-ico-from-exe-and-paint-with-pyqt shows how you have to do this. Read each answer carefully, and the little comments, to allow for PyQt6 (or PySide6).

          If you can translate the few lines of https://stackoverflow.com/a/50809652/489865 into PyQt/PySide and it works on an exe that's even simpler.

          M Offline
          M Offline
          Mizmas
          wrote on last edited by Mizmas
          #4

          @JonB Thanks a lot. Apparently the QFileIconProvider class was removed from PyQt6, but QFileSystemModel can be used instead.

          Here's the updated code, it now successfully creates a QIcon for .exe icon paths. On my system there's still some application icon paths that aren't being found by the get_installed_apps_from_registry method, or maybe they just don't exist in the registry, so maybe someone will be able to improve upon this code:

          import sys
          import os
          import winreg
          from PyQt6.QtWidgets import QApplication, QComboBox, QMainWindow
          from PyQt6.QtGui import QIcon, QFileSystemModel
          from PyQt6.QtCore import QSize
          
          
          def get_installed_apps_from_registry(registry_path):
              apps = []
              try:
                  reg_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0, winreg.KEY_READ)
                  for i in range(0, winreg.QueryInfoKey(reg_key)[0]):
                      try:
                          subkey_name = winreg.EnumKey(reg_key, i)
                          subkey = winreg.OpenKey(reg_key, subkey_name)
          
                          # Retrieve app name
                          app_name, _ = winreg.QueryValueEx(subkey, "DisplayName")
          
                          # Retrieve app icon path
                          try:
                              icon_path, _ = winreg.QueryValueEx(subkey, "DisplayIcon")
                              icon_path = icon_path.split(",")[0].strip()  # Clean up icon path
                              if not os.path.isfile(icon_path):
                                  icon_path = None
                          except FileNotFoundError:
                              icon_path = None
          
                          # Append app name and icon path to the list
                          apps.append({"name": app_name, "icon": icon_path})
                      except EnvironmentError:
                          continue
                      finally:
                          subkey.Close()
              except EnvironmentError:
                  pass
              return apps
          
          
          def list_installed_apps():
              registry_paths = [
                  r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                  r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
              ]
              installed_apps = []
              for path in registry_paths:
                  installed_apps.extend(get_installed_apps_from_registry(path))
          
              # Remove duplicates and sort
              unique_apps = {app['name']: app for app in installed_apps if app['name']}
              sorted_apps = sorted(unique_apps.values(), key=lambda x: x['name'])
              return sorted_apps
          
          
          class AppComboBox(QMainWindow):
              def __init__(self, apps):
                  super().__init__()
                  self.setWindowTitle("Installed Applications")
                  self.setGeometry(100, 100, 400, 100)
          
                  # Create QComboBox
                  self.combo = QComboBox(self)
                  self.combo.setIconSize(QSize(32, 32))
                  self.combo.setGeometry(50, 20, 300, 40)
          
                  # Initialize QFileSystemModel to fetch icons
                  self.file_model = QFileSystemModel()
          
                  # Add apps to combo box with icons
                  for app in apps:
                      icon = self.get_icon(app['icon']) if app['icon'] else QIcon()
                      self.combo.addItem(icon, app['name'])
          
              def get_icon(self, icon_path):
                  # Fetches an icon using QFileSystemModel based on file path
                  if icon_path and os.path.isfile(icon_path):
                      index = self.file_model.index(icon_path)
                      return self.file_model.fileIcon(index)
                  return QIcon()  # Return an empty icon if path is invalid
          
          
          def main():
              # Fetch installed applications
              apps = list_installed_apps()
          
              # Print program name and icon path
              for app in apps:
                  print(f"Name: {app['name']}")
                  print(f"Icon Path: {app['icon']}")
                  print("-" * 40)
          
              # Set up the PyQt6 application
              app = QApplication(sys.argv)
              window = AppComboBox(apps)
              window.show()
              sys.exit(app.exec())
          
          
          if __name__ == "__main__":
              main()
          
          
          1 Reply Last reply
          2
          • M Mizmas has marked this topic as solved on

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved