在windows-rs项目中调用winget WinRT COM API的实践指南
背景介绍
Windows Package Manager(winget)是微软推出的现代化包管理工具,它通过WinRT COM API提供了丰富的功能接口。对于Rust开发者而言,通过windows-rs项目可以方便地调用这些原生Windows API。本文将详细介绍如何在Rust中使用windows-rs来调用winget的WinRT COM API。
准备工作
首先需要确保开发环境满足以下条件:
- 安装最新版本的Windows SDK
- 在Cargo.toml中添加必要的依赖项
- 获取Microsoft.Management.Deployment.winmd元数据文件
核心实现步骤
1. 项目配置
在Cargo.toml中添加windows和windows-core依赖,并启用必要的特性:
[dependencies]
windows-core = "0.58.0"
[dependencies.windows]
version = "0.58.0"
features = [
"Foundation_Collections",
"System",
"Win32_System_Com",
]
2. 生成Rust绑定
使用windows-bindgen工具从winmd文件生成Rust绑定代码:
// build.rs
fn main() {
if !cfg!(target_env = "msvc") {
return;
}
println!("cargo:rustc-link-lib=onecoreuap");
windows_bindgen::bindgen([
"--in",
"winmd/Microsoft.Management.Deployment.winmd",
"--out",
"src/bindings.rs",
"--filter",
"Microsoft.Management.Deployment",
"--config",
"no-bindgen-comment",
])
.unwrap();
}
3. 关键实现细节
创建COM实例时需要注意将winmd文件放在可执行文件同级目录下,因为winget使用了Packaged COM技术,系统需要这些元数据来确定接口的封送处理行为。
// 创建COM实例的辅助函数
fn create_standard_instance<T: windows_core::Interface>(clsid: &GUID) -> windows_core::Result<T> {
unsafe {
let object: IUnknown = CoCreateInstance(clsid, None, CLSCTX_LOCAL_SERVER)?;
object.cast::<T>()
}
}
4. 完整示例代码
以下是一个完整的示例,展示了如何连接winget包管理器并搜索指定包:
#![cfg(target_env = "msvc")]
mod bindings;
use windows::Win32::System::Com::{CoCreateInstance, CoInitialize, CLSCTX_LOCAL_SERVER};
use windows_core::{h, IUnknown, Interface, GUID};
// 定义所有需要的CLSID
static PACKAGE_MANAGER_CLSID: GUID = GUID::from_u128(0xC53A4F16_787E_42A4_B304_29EFFB4BF597);
static FIND_PACKAGES_OPTIONS_CLSID: GUID = GUID::from_u128(0x572DED96_9C60_4526_8F92_EE7D91D38C1A);
static CREATE_COMPOSITE_PACKAGE_CATALOG_OPTIONS_CLSID: GUID =
GUID::from_u128(0x526534B8_7E46_47C8_8416_B1685C327D37);
static PACKAGE_MATCH_FILTER_CLSID: GUID = GUID::from_u128(0xD02C9DAF_99DC_429C_B503_4E504E4AB000);
fn main() -> windows_core::Result<()> {
unsafe { CoInitialize(None).ok()?; }
// 创建包管理器实例
let package_manager = create_standard_instance::<PackageManager>(&PACKAGE_MANAGER_CLSID)?;
// 获取winget和msstore目录
let winget_catalog = package_manager.GetPackageCatalogByName(h!("winget"))?;
let msstore_catalog = package_manager.GetPackageCatalogByName(h!("msstore"))?;
// 配置复合目录选项
let composite_catalog_options = create_standard_instance::<CreateCompositePackageCatalogOptions>(
&CREATE_COMPOSITE_PACKAGE_CATALOG_OPTIONS_CLSID,
)?;
composite_catalog_options.Catalogs()?.Append(&winget_catalog)?;
composite_catalog_options.Catalogs()?.Append(&msstore_catalog)?;
composite_catalog_options.SetCompositeSearchBehavior(CompositeSearchBehavior::LocalCatalogs)?;
composite_catalog_options.SetInstalledScope(PackageInstallScope::Any)?;
// 连接包目录
let connect_result = package_manager
.CreateCompositePackageCatalog(&composite_catalog_options)?
.Connect()?;
if connect_result.Status()? != ConnectResultStatus::Ok {
panic!("连接包目录失败");
}
// 创建搜索选项
let find_packages_options =
create_standard_instance::<FindPackagesOptions>(&FIND_PACKAGES_OPTIONS_CLSID)?;
// 添加搜索过滤器
let match_filter = create_standard_instance::<PackageMatchFilter>(&PACKAGE_MATCH_FILTER_CLSID)?;
match_filter.SetField(PackageMatchField::Id)?;
match_filter.SetOption(PackageFieldMatchOption::Equals)?;
match_filter.SetValue(h!("Git.Git"))?;
find_packages_options.Selectors()?.Append(&match_filter)?;
// 执行搜索
let find_result = connect_result
.PackageCatalog()?
.FindPackages(&find_packages_options)?;
// 处理搜索结果
for result in find_result.Matches()? {
let catalog_package = result.CatalogPackage()?;
println!(
"{} - {}",
catalog_package.Id()?,
catalog_package.Name()?
);
}
Ok(())
}
技术要点解析
-
Packaged COM的特殊处理:winget API使用了Packaged COM技术,这意味着系统不会在注册表中查找接口信息,而是直接从winmd元数据文件中获取。因此必须确保winmd文件与可执行文件位于同一目录。
-
接口转换:通过
cast
方法可以将基础的IUnknown接口转换为具体的接口类型,这是COM编程中的常见模式。 -
错误处理:windows-rs提供了良好的错误处理机制,所有COM调用都返回Result类型,便于开发者处理各种错误情况。
-
多线程考虑:示例中使用了
CoInitialize
初始化COM库,在实际应用中需要考虑多线程环境下的COM初始化策略。
高级应用场景
掌握了基础用法后,还可以实现更复杂的功能:
-
包安装与卸载:通过
InstallOptions
和UninstallOptions
接口实现包的安装和卸载功能。 -
提升权限运行:当需要管理员权限时,可以使用
WinGetServerManualActivation_CreateInstance
函数创建提升的实例。 -
进度监控:通过实现特定的回调接口来监控包操作的进度。
总结
通过windows-rs项目调用winget WinRT COM API是一个强大而灵活的方式,可以让Rust开发者充分利用Windows平台的包管理能力。本文介绍了从环境配置到实际调用的完整流程,并提供了可直接运行的示例代码。掌握这些技术后,开发者可以构建出功能丰富的Windows包管理工具,满足各种自动化部署和软件管理需求。
- DDeepSeek-V3.1-BaseDeepSeek-V3.1 是一款支持思考模式与非思考模式的混合模型Python00
- QQwen-Image-Edit基于200亿参数Qwen-Image构建,Qwen-Image-Edit实现精准文本渲染与图像编辑,融合语义与外观控制能力Jinja00
GitCode-文心大模型-智源研究院AI应用开发大赛
GitCode&文心大模型&智源研究院强强联合,发起的AI应用开发大赛;总奖池8W,单人最高可得价值3W奖励。快来参加吧~050CommonUtilLibrary
快速开发工具类收集,史上最全的开发工具类,欢迎Follow、Fork、StarJava04GitCode百大开源项目
GitCode百大计划旨在表彰GitCode平台上积极推动项目社区化,拥有广泛影响力的G-Star项目,入选项目不仅代表了GitCode开源生态的蓬勃发展,也反映了当下开源行业的发展趋势。06GOT-OCR-2.0-hf
阶跃星辰StepFun推出的GOT-OCR-2.0-hf是一款强大的多语言OCR开源模型,支持从普通文档到复杂场景的文字识别。它能精准处理表格、图表、数学公式、几何图形甚至乐谱等特殊内容,输出结果可通过第三方工具渲染成多种格式。模型支持1024×1024高分辨率输入,具备多页批量处理、动态分块识别和交互式区域选择等创新功能,用户可通过坐标或颜色指定识别区域。基于Apache 2.0协议开源,提供Hugging Face演示和完整代码,适用于学术研究到工业应用的广泛场景,为OCR领域带来突破性解决方案。00openHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!C0302- WWan2.2-S2V-14B【Wan2.2 全新发布|更强画质,更快生成】新一代视频生成模型 Wan2.2,创新采用MoE架构,实现电影级美学与复杂运动控制,支持720P高清文本/图像生成视频,消费级显卡即可流畅运行,性能达业界领先水平Python00
- GGLM-4.5-AirGLM-4.5 系列模型是专为智能体设计的基础模型。GLM-4.5拥有 3550 亿总参数量,其中 320 亿活跃参数;GLM-4.5-Air采用更紧凑的设计,拥有 1060 亿总参数量,其中 120 亿活跃参数。GLM-4.5模型统一了推理、编码和智能体能力,以满足智能体应用的复杂需求Jinja00
Yi-Coder
Yi Coder 编程模型,小而强大的编程助手HTML013
热门内容推荐
最新内容推荐
项目优选









