菜单

模块加载系统

相关源文件

PowerToys 中的模块加载系统负责动态加载、初始化和管理所有 PowerToys 工具的生命周期。它提供了一个插件架构,允许单独开发各个工具,同时与 PowerToys 运行程序保持一致的接口。

本页介绍了 PowerToys 如何发现、加载和与模块 DLL 进行交互。有关创建新 PowerToy 模块的信息,请参阅创建新 PowerToy

概述

PowerToys 使用模块化架构,其中每个工具都实现为一个单独的 DLL,并实现通用接口。PowerToys 运行程序 (PowerToys.exe) 负责:

  1. 发现可用的 PowerToys 模块
  2. 将这些模块加载到内存中
  3. 根据保存的设置初始化和配置模块
  4. 根据用户偏好启用/禁用模块
  5. 管理模块生命周期(启动、关闭、配置更改)
  6. 在 UI 和模块之间提供 IPC

架构

来源

模块接口

所有 PowerToys 模块都必须实现PowertoyModuleIface接口,该接口定义了运行程序和每个模块之间的契约。此接口在powertoy_module_interface.h中定义。

接口的关键方法包括:

方法目的
get_name()返回模块的本地化显示名称
get_key()返回模块的非本地化唯一标识符
enable()激活模块的功能
disable()禁用模块的功能
is_enabled()返回模块当前是否已启用
get_config()以 JSON 格式返回模块的当前配置
set_config()将新的配置设置应用于模块
call_custom_action()处理从“设置” UI 触发的自定义操作
destroy()在模块卸载前清理资源

来源

模块加载过程

已知模块发现

PowerToys 运行程序维护一个已知模块列表,这些模块被定义为 DLL 路径数组。

来源

加载顺序

模块加载过程遵循以下步骤:

  1. 在初始化期间,运行程序会遍历已知模块 DLL 列表。
  2. 对于每个模块,它会调用load_powertoy(),该函数会:
    • 使用本机 Windows 函数将 DLL 加载到内存中。
    • 查找导出的powertoy_create()函数。
    • 调用此函数以创建模块类的实例。
    • 返回指向实现PowertoyModuleIface接口的模块的指针。
  3. 模块实例以模块的 key 作为标识符存储在一个映射表中。
  4. 加载完所有模块后,运行程序会调用start_enabled_powertoys()来激活之前启用的模块。

来源

模块存储和管理

已加载的模块存储在一个映射表中,其中:

  • Key 是模块的唯一标识符字符串(由get_key()返回)。
  • Value 是PowertoyModuleIface实例的智能指针。

该集合通过modules()函数访问,该函数返回此映射表的引用。

来源

模块生命周期管理

初始化

  1. 当模块首次加载时,会调用其构造函数。
  2. 模块通常会加载其设置并初始化其内部状态。
  3. 在调用其enable()方法之前,模块将保持非活动状态。

启用与禁用

  1. 当运行程序调用模块的enable()方法时:
    • 模块激活其功能。
    • 设置钩子、注册事件或执行其他初始化。
    • 通常创建任何必需的 UI 元素。
  2. 当运行程序调用模块的disable()方法时:
    • 模块禁用其功能。
    • 清理钩子、事件注册和资源。
    • 通常销毁任何创建的 UI 元素。

配置

  1. 运行程序可以通过调用模块的get_config()方法来检索模块的当前配置。
  2. 模块以 JSON 字符串形式返回其设置。
  3. 运行程序可以通过使用新的 JSON 配置调用模块的set_config()方法来更新模块的配置。
  4. 模块解析 JSON 并应用新设置。

来源

清理和卸载

  1. 当 PowerToys 关闭时,运行程序会调用每个模块的destroy()方法。
  2. 模块清理资源并准备卸载。
  3. 模块从destroy()返回后,运行程序会释放其对该模块的引用。
  4. 一旦所有引用都已释放,就会调用模块的析构函数。
  5. 然后,DLL 会从内存中卸载。

来源

实现 PowerToy 模块

要实现 PowerToy 模块,DLL 必须:

  1. 实现PowertoyModuleIface接口。
  2. 导出powertoy_create()函数,该函数返回模块的实例。

以下是模块 DLL 的典型结构。

示例:PowerRename 模块实现

PowerRename 是 PowerToy 模块实现的绝佳示例。

来源

错误处理

加载模块时,运行程序会实现错误处理,以确保一个模块的故障不会影响其他模块。

  1. 每个模块都加载在 try/catch 块中。
  2. 如果加载失败,会显示错误消息,但运行程序会继续加载其他模块。
  3. 在调试构建中,可以获得更详细的错误信息以进行故障排除。

来源

组策略集成

PowerToys 模块可以与 Windows 组策略设置集成,以允许管理员控制可用功能。

  1. 每个模块都实现了一个gpo_policy_enabled_configuration()方法。
  2. 此方法检查组策略是否已显式启用或禁用该模块。
  3. 在确定模块是否可以启用时,运行程序会尊重这些策略设置。

来源