Rust使用windows crate获取关联产品列表时遇错误87(参数错误)
我在Rust中使用windows crate,尝试根据给定的升级码获取关联产品列表,但代码返回错误87(-2147024809):参数设置不正确。我尝试的代码如下:
use windows::Win32::System::ApplicationInstallationAndServicing::MsiEnumRelatedProductsA; use winapi::shared::winerror::HRESULT_FROM_WIN32; fn main() { let upgrade_code = "23170F69-40C1-2702-0000-000004000000"; // Enumerate related products and print their names let mut index = 0; loop { let mut product_buf = vec![0u8; 1024]; let result = unsafe { MsiEnumRelatedProductsA( windows::core::PCSTR(upgrade_code.as_ptr()), 0, index, windows::core::PSTR(product_buf.as_mut_ptr()), ) }; if result == 0 { // Convert the null-terminated byte array to a string and print the results let product_list = String::from_utf8(product_buf).unwrap_or("".to_string()); println!("Related products: {}", product_list); break; } else if result != 259 { //259 = No additional data available println!("Error code: {} ({})",result, HRESULT_FROM_WIN32(result)); break; } index += 1; } }
问题分析与修正
- 升级码格式错误:
MsiEnumRelatedProductsA要求升级码必须用大括号{}包裹,原代码中的升级码缺少大括号,这是触发错误87的直接原因。 - 字符串转换错误:直接将整个缓冲区转字符串会包含大量无效的0字节,应该截取到第一个null字符的位置再转换。
- 循环逻辑错误:原代码获取第一个产品后就终止循环,无法枚举所有关联产品;同时错误码259(
ERROR_NO_MORE_ITEMS)表示没有更多数据,此时才应该终止循环。
修正后的代码
use windows::Win32::System::ApplicationInstallationAndServicing::{MsiEnumRelatedProductsA, ERROR_NO_MORE_ITEMS}; use winapi::shared::winerror::HRESULT_FROM_WIN32; fn main() { // 升级码必须用大括号包裹 let upgrade_code = "{23170F69-40C1-2702-0000-000004000000}"; let mut index = 0; loop { let mut product_buf = vec![0u8; 39]; // Product ID固定为38字符+null终止符,不需要1024这么大 let result = unsafe { MsiEnumRelatedProductsA( windows::core::PCSTR(upgrade_code.as_ptr()), 0, index, windows::core::PSTR(product_buf.as_mut_ptr()), ) }; match result { 0 => { // 截取到第一个null字符的位置,转换为有效字符串 if let Some(null_pos) = product_buf.iter().position(|&b| b == 0) { let product_id = String::from_utf8_lossy(&product_buf[..null_pos]); println!("关联产品ID: {}", product_id); } index += 1; } ERROR_NO_MORE_ITEMS => { println!("已枚举所有关联产品"); break; } err => { println!("错误代码: {} ({})", err, HRESULT_FROM_WIN32(err)); break; } } } }
关键修改说明
- 给升级码添加了强制要求的大括号
{}; - 缩小了缓冲区大小,因为Windows Installer的产品ID固定为38个字符(GUID格式),加上null终止符只需要39字节;
- 修复了字符串转换逻辑,只截取到第一个null字符前的有效部分;
- 调整循环逻辑,成功获取产品后继续枚举下一个,直到遇到
ERROR_NO_MORE_ITEMS才终止; - 直接使用windows crate中定义的
ERROR_NO_MORE_ITEMS常量,避免硬编码数值。
内容的提问来源于stack exchange,提问作者Moris
相关产品推荐
相关产品推荐

