C#调用MsiSourceListEnumSources获取MSI源位置时遇无效参数错误
排查MsiSourceListEnumSources返回invalid_parameter错误的要点
嘿,我来帮你揪出这个API调用报错的问题!结合你给出的代码片段,咱们从几个常见的坑入手排查:
枚举值与参数类型必须严格匹配
先检查MsiInstallContext和MsiCode这两个自定义枚举的定义,必须和Windows官方API文档完全一致:MsiInstallContext的有效值只能是MSIINSTALLCONTEXT_USERMANAGED (1)、MSIINSTALLCONTEXT_USERUNMANAGED (2)、MSIINSTALLCONTEXT_MACHINE (4),自定义值写错直接触发参数错误。dwOptions(对应MsiCode)要和传入的szProductOrPatchCode类型对应:传产品GUID就用MSICODE_PRODUCT (0),传补丁代码就用MSICODE_PATCH (1),搞反了绝对会报错。
StringBuilder缓冲区必须正确初始化
这个API对szSource和pcchSource的要求很严格,不能直接传空的或者容量为0的StringBuilder:
正确的做法是先调用一次API获取需要的缓冲区大小,再初始化StringBuilder后二次调用,示例代码如下:int bufferSize = 0; // 第一次调用:获取所需缓冲区的大小 MsiError firstCallResult = MsiSourceListEnumSources( productCode, null, MsiInstallContext.MACHINE, MsiCode.MSICODE_PRODUCT, 0, null, ref bufferSize); if (firstCallResult == MsiError.SUCCESS || firstCallResult == MsiError.MOREDATA) { StringBuilder sourceBuffer = new StringBuilder(bufferSize); // 第二次调用:获取实际的源位置 MsiError secondCallResult = MsiSourceListEnumSources( productCode, null, MsiInstallContext.MACHINE, MsiCode.MSICODE_PRODUCT, 0, sourceBuffer, ref bufferSize); }如果跳过这一步直接传未初始化的缓冲区,或者
pcchSource的值和缓冲区容量不匹配,必然会返回参数错误。用户SID与上下文要对应
- 如果
dwContext指定的是机器上下文(MACHINE),szUserSid必须传null或者空字符串,传其他无效SID肯定会报错。 - 如果是用户上下文(
USERMANAGED/USERUNMANAGED),szUserSid必须是格式正确的用户SID字符串(比如"S-1-5-21-XXXXXX-XXXXXX-XXXXXX-1001"),不能瞎填。
- 如果
产品/补丁代码格式要规范
szProductOrPatchCode必须是带大括号的标准GUID格式,比如"{12345678-1234-1234-1234-1234567890AB}",漏了大括号或者格式错误的话,API根本识别不了,直接返回参数错误。Marshal特性与枚举基础类型要一致
确认MsiError枚举的基础类型是uint(因为API返回的是32位无符号整数),如果默认用了int,可能会导致类型不匹配。另外DllImport的CharSet.Auto要和字符串参数的处理一致,不要出现字符集冲突的情况。
内容的提问来源于stack exchange,提问作者user1403598
相关产品推荐
相关产品推荐

