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

调用GetZoneMappings后IEnumString.Next()始终返回0项,如何修正?

解决IEnumString.Next()返回项数始终为0的问题

问题根源

你的代码存在两个核心问题导致nItemsFetched始终为0:

  • 输出参数传递错误:GetZoneMappings的枚举对象参数、Next方法的项数参数均为COM输出参数,需用ByRef传递,否则COM无法修改托管代码中的变量值。
  • 数据类型不匹配:nItemsFetched使用了ULong,但COM接口定义中对应类型是ULONG(即VB中的UInteger),类型不匹配会导致参数传递异常。

修正后的完整代码

Imports System
Imports System.Collections.Generic
Imports System.Runtime.InteropServices

Public Class Test
    Private Shared ReadOnly CLSID_InternetSecurityManager As New Guid("7b8a2d94-0ac9-11d1-896c-00c04fb6bfc4")
    Private ReadOnly InternetSecurityManager As IInternetSecurityManager

    Private Const URLZONE_LOCAL_MACHINE As UInteger = &H0
    Private Const URLZONE_INTRANET As UInteger = URLZONE_LOCAL_MACHINE + 1
    Private Const URLZONE_TRUSTED As UInteger = URLZONE_INTRANET + 1
    Private Const URLZONE_INTERNET As UInteger = URLZONE_TRUSTED + 1
    Private Const URLZONE_UNTRUSTED As UInteger = URLZONE_INTERNET + 1

    Public Sub New()
        Dim secManagerType = Type.GetTypeFromCLSID(CLSID_InternetSecurityManager)
        InternetSecurityManager = CType(Activator.CreateInstance(secManagerType), IInternetSecurityManager)
        Dim sites = GetSites()
    End Sub

    Private Function GetSites() As List(Of String)
        Dim enumString As IEnumString = Nothing
        Dim sites As New List(Of String)()
        Dim items As String() = New String(0) {}
        Dim fetched As UInteger

        InternetSecurityManager.GetZoneMappings(URLZONE_INTRANET, enumString, 0)

        Do
            ' Next返回S_OK(0)表示成功获取项,S_FALSE(1)表示无更多项
            Dim hr = enumString.Next(1, items, fetched)
            If hr <> 0 OrElse fetched = 0 Then
                Exit Do
            End If
            sites.Add(items(0))
        Loop

        Return sites
    End Function

    ' 正确定义IInternetSecurityManager接口,仅保留用到的GetZoneMappings方法
    <ComImport>
    <Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b")>
    <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Private Interface IInternetSecurityManager
        Sub GetZoneMappings(<[In]> dwZone As UInteger, <Out> ByRef ppenumString As IEnumString, <[In]> dwFlags As UInteger)
        ' 若需要其他方法,可根据MSDN文档补充签名
    End Interface

    ' 正确定义IEnumString接口,匹配COM规范
    <ComImport>
    <Guid("00000101-0000-0000-C000-000000000046")>
    <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Private Interface IEnumString
        Function Next(<[In]> celt As UInteger, <Out()> rgelt As String(), <Out> ByRef pceltFetched As UInteger) As Integer
        Sub Skip(<[In]> celt As UInteger)
        Sub Reset()
        Sub Clone(<Out> ByRef ppenum As IEnumString)
    End Interface
End Class

关键修正说明

  1. 接口定义修正
    • 手动定义IInternetSecurityManager和IEnumString接口,确保参数传递符合COM规范:
      • GetZoneMappings的ppenumString用ByRef声明,让COM能返回枚举对象。
      • IEnumString.Next的pceltFetched用ByRef声明,让COM能写入实际获取的项数。
  2. 循环逻辑优化
    • 通过Next方法的返回值(S_OK/S_FALSE)结合fetched值判断循环终止条件,无需再检查字符串是否为Nothing。
  3. 数据类型对齐
    • 将fetched改为UInteger,匹配COM接口的ULONG类型,避免类型转换错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:06:51