You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust使用windows crate获取关联产品列表时遇错误87(参数错误)

Rust中调用MsiEnumRelatedProductsA返回错误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;
            }
        }
    }
}

关键修改说明

  1. 给升级码添加了强制要求的大括号{};
  2. 缩小了缓冲区大小,因为Windows Installer的产品ID固定为38个字符(GUID格式),加上null终止符只需要39字节;
  3. 修复了字符串转换逻辑,只截取到第一个null字符前的有效部分;
  4. 调整循环逻辑,成功获取产品后继续枚举下一个,直到遇到ERROR_NO_MORE_ITEMS才终止;
  5. 直接使用windows crate中定义的ERROR_NO_MORE_ITEMS常量,避免硬编码数值。

内容的提问来源于stack exchange,提问作者Moris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:37:37