诊断 Windows 运行时组件错误条件

本文提供了有关用托管代码编写的 Windows 运行时组件所受限制的附加信息。 它对来自 Winmdexp.exe(Windows 运行时元数据导出工具)的错误消息所提供的信息进行了扩展,对用 C# 和 Visual Basic 创建 Windows 运行时组件中提供的限制信息进行了补充。

本文并未涵盖所有错误。 此处讨论的错误按常规类别分组,并且每个类别包括一个由关联的错误消息组成的表。 搜索消息文本(省略占位符的特定值)或消息编号。 如果在此处找不到所需信息,请使用本文末尾的反馈按钮帮助我们改进文档。 包括错误消息。 也可以在 Microsoft Connect 网站提交 Bug。

本文包含以下几个部分:

  • 当实现异步模式时,错误消息提供不正确的类型

  • 缺少对 mscorlib.dll 和/或 System.Runtime.dll 的引用

  • 不允许运算符重载

  • 类的构造函数具有相同数量的参数

  • 必须为具有相同数量参数的重载指定默认值

  • 命名空间错误和输出文件的名称无效

  • 导出不是有效的 Windows 运行时类型的类型

  • 包含禁用类型的字段的结构

  • 对于成员签名中数组的限制

  • 数组参数必须指定数组内容是否可读或可写

  • 具有名为“value”的参数的成员

实现异步接口的错误消息提供不正确的类型

托管 Windows 运行时 组件无法实现 Windows 运行时 表示异步操作(IAsyncActionIAsyncActionWithProgress<TProgress>IAsyncOperation<TResult>,或 IAsyncOperationWithProgress<TResult, TProgress>)的接口。 相反,.NET Framework 提供 AsyncInfo 类,用以在 Windows 运行时 组件中生成异步操作。 当您尝试实现一个按以前的名称 AsyncInfoFactory 不正确地引用该类的异步接口时显示的 Winmdexp.exe 错误消息。 .NET Framework 不再包括 AsyncInfoFactory 类。

错误号

消息正文

WME1084

类型“{0}”实现 Windows 运行时异步接口“{1}”。 Windows 运行时类型不能实现异步接口。 请使用 System.Runtime.InteropServices.WindowsRuntime.AsyncInfoFactory 类生成异步操作以便导出到 Windows 运行时。

缺少对 mscorlib.dll 或 System.Runtime.dll 的引用

仅当从命令行使用 Winmdexp.exe 时,才会出现此问题。 建议使用 /reference 选项来包括对 .NET Framework 核心引用程序集中的 mscorlib.dll 和 System.Runtime.dll 的引用,这些程序集位于“%ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5”(32 位计算机上则为“%ProgramFiles%\...”)中。

错误号

消息正文

WME1009

未引用 mscorlib.dll。需要使用对此元数据文件的引用才能正确进行导出。

WME1090

无法确定核心引用程序集。 请确保使用 /reference 开关引用 mscorlib.dll 和 System.Runtime.dll。

不允许运算符重载

在用托管代码编写的 Windows 运行时组件中,不能在公共类型中公开重载运算符。

备注

在错误消息中,运算符由其元数据名称标识,如 op_Addition、op_Multiply、op_ExclusiveOr、op_Implicit(隐式转换)等。

错误号

消息正文

WME1087

“{0}”是运算符重载。 托管类型不能在 Windows 运行时中公开运算符重载。

类的构造函数具有相同数量的参数

在 Windows 运行时中,一个类只能有一个构造函数,而该构造函数只能有给定数量的参数;例如,不能让一个构造函数具有单个类型为 String 的参数,而让另一个构造函数具有单个类型为 int(在 Visual Basic 中为 Integer)的参数。 唯一的解决方法是让每个构造函数使用不同数量的参数。

错误号

消息正文

WME1099

类型“{0}”具有多个带“{1}”参数的构造函数。 Windows 运行时 类型不能拥有带相同数量参数的多个构造函数。

必须为具有相同数量参数的重载指定默认值

在 Windows 运行时中,仅当将某一重载指定为默认重载时,重载方法才可以具有相同数量的参数。 请参见用 C# 和 Visual Basic 创建 Windows 运行时组件中的“重载方法”。

错误号

消息正文

WME1059

“{1}.{2}”的多个 {0}-参数重载使用 Windows.Foundation.Metadata.DefaultOverloadAttribute 进行了修饰。

WME1085

{1}.{2} 的 {0}-参数重载必须刚好有一个通过使用 Windows.Foundation.Metadata.DefaultOverloadAttribute 修饰来指定为默认重载的方法。

命名空间错误和输出文件的名称无效

在 Windows 运行时中,Windows 元数据 (.winmd) 文件中的所有公共类型必须在一个共享 .winmd 文件名的命名空间中,或在该文件名的子命名空间中。 例如,如果 Visual Studio 2012 项目命名为 A.B(即 Windows 运行时组件为 A.B.winmd),则可包含公共类 A.B.Class1 和 A.B.C.Class2,但不可包含 A.Class3 (WME0006) 或 D.Class4 (WME1044)。

备注

这些限制仅适用于公共类型,不适用于在实现中使用的私有类型。

对于 A.Class3,可将 Class3 移至另一个命名空间或将 Windows 运行时组件的名称更改为 A.winmd。 虽然 WME0006 是警告,应将其视为错误。 在前面的示例中,调用 A.B.winmd 的代码将无法查找 A.Class3。

对于 D.Class4,任何文件名都不能同时包含 D.Class4 和 A.B 命名空间中的类,因此无法更改 Windows 运行时组件的名称。 可将 D.Class4 移至其他命名空间,或将其放入其他 Windows 运行时组件。

文件系统无法区分大小写,因此不允许使用按大小写区分的命名空间 (WME1067)。

你的组件必须至少包含一个 public sealed 类型(在 Visual Basic 中为 Public NotInheritable)。 否则,将收到 WME1042 或 WME1043,具体取决于组件是否包含私有类型。

Windows 运行时组件中的类型不能与命名空间同名 (WME1068)。

警告

如果直接调用 Winmdexp.exe 并且不使用 /out 选项为 Windows 运行时组件指定名称,Winmdexp.exe 将尝试生成一个包括组件中所有命名空间的名称。对命名空间重命名可以更改组件的名称。

错误号

消息正文

WME0006

“{0}”对于此程序集是无效的 winmd 文件名。Windows 元数据文件中的所有类型都必须存在于该文件名所隐含的命名空间的子命名空间中。在运行时无法定位不存在于此类子命名空间中的类型。在此程序集中,可用作文件名的最小公共命名空间为“{1}”。

WME1042

输入模块必须至少包含一个位于命名空间中的公共类型。

WME1043

输入模块必须至少包含一个位于命名空间中的公共类型。 在命名空间中找到的唯一类型是私有类型。

WME1044

公共类型具有不与其他命名空间(“{0}”)共享公共前缀的命名空间(“{1}”)。 Windows 元数据文件中的所有类型都必须存在于该文件名所隐含的命名空间的子命名空间中。

WME1067

命名空间名称不能仅通过大小写来区分:“{0}”,“{1}”。

WME1068

类型“{0}”不能与命名空间“{1}”同名。

导出不是有效的 Windows 运行时类型的类型

组件的公共接口必须只公开 Windows 运行时类型。 但是,.NET framework 可为在 .NET framework 和 Windows 运行时中略有不同的许多常用类型提供映射。 这使得 .NET Framework 开发人员可以使用熟悉的类型,而不是学习新类型。 可在组件的公共接口中使用这些映射的 .NET Framework 类型。 请参见用 C# 和 Visual Basic 创建 Windows 运行时组件Windows 运行时类型的 .NET Framework 映射中的“在 Windows 运行时组件中声明类型”和“将 Windows 运行时类型传递给托管代码”。

其中许多映射都是接口。 例如,IList<T> 映射到 Windows 运行时 接口 IVector<T>。 如果使用 List<string>(在 Visual Basic 中为 List(Of String))而不是 IList<string> 作为参数类型,Winmdexp.exe 将提供替代项的列表,其中包括 List<T> 所实现的所有映射接口。 如果使用嵌套的泛型类型,如 List<Dictionary<int, string>>(在 Visual Basic 中为 List(Of Dictionary(Of Integer, String))),Winmdexp.exe 将针对每个嵌套级别提供选择。 这些列表可能变得相当长。

通常,最佳选择是最接近类型的接口。 例如,对于 Dictionary<int, string>,最佳选择最可能是 IDictionary<int, string>。

重要

JavaScript 使用托管类型实现的、在接口列表中显示在最前面的接口。例如,如果将 Dictionary<int, string> 返回给 JavaScript 代码,那么无论你将哪个接口指定为返回类型,它都显示为 IDictionary<int, string>。这意味着,如果第一个接口不包括在后续接口中出现的成员,该成员将对 JavaScript 不可见。

警告

如果 JavaScript 要使用你的组件,请不要使用非泛型的 IListIEnumerable 接口。这些接口分别映射到 IBindableVectorIBindableIterator。它们支持对 XAML 控件的绑定,对 JavaScript 不可见。JavaScript 发出运行时错误“函数‘X’的签名无效,无法调用”。

错误号

消息正文

WME1033

方法“{0}”具有类型为“{2}”的参数“{1}”。“{2}”是无效的 Windows 运行时参数类型。

WME1038

方法“{0}”的签名中具有“{1}”类型的参数。虽然此类型不是有效的 Windows 运行时类型,但它可实现属于有效 Windows 运行时类型的接口。请考虑更改方法签名,以改用以下类型之一:“{2}”。

WME1039

方法“{0}”的签名中具有“{1}”类型的参数。 尽管此泛型类型是无效的 Windows 运行时类型,但此类型或其泛型参数实现了作为有效 Windows 运行时类型的接口。{2}

说明说明
对于 {2},Winmdexp.exe 会附加一个替代项列表,例如“考虑将方法签名中的类型‘System.Collections.Generic.List<T>’更改为以下类型之一:‘System.Collections.Generic.IList<T>、System.Collections.Generic.IReadOnlyList<T>、System.Collections.Generic.IEnumerable<T>’。”

WME1040

方法“{0}”的签名中具有“{1}”类型的参数。请使用 Windows.Foundation.IAsyncAction、Windows.Foundation.IAsyncOperation 或其他 Windows 运行时异步接口之一,而不是使用托管任务类型。 标准 .NET 等待模式也适用于这些接口。有关将托管任务对象转换为 Windows 运行时异步接口的详细信息,请参见 System.Runtime.InteropServices.WindowsRuntime.AsyncInfo。

包含禁用类型的字段的结构

在 Windows 运行时中,结构只能包含字段,并且只有结构可以包含字段。 这些字段必须是公共的。 有效字段类型包括枚举、结构和基元类型。

错误号

消息正文

WME1060

结构“{0}”具有“{2}”类型的字段“{1}”。“{2}”是无效的 Windows 运行时字段类型。 Windows 运行时结构中的每个字段都只能是 UInt8、Int16、UInt16、Int32、UInt32、Int64、UInt64、Single、Double、Boolean、String、Enum 或自身为结构。

对于成员签名中数组的限制

在 Windows 运行时中,成员签名中的数组必须是下限为 0(零)的一维数组。 不允许使用嵌套数组类型,如 myArray[][](在 Visual Basic 中为 myArray()())。

备注

此限制不适用于在实现内部使用的数组。

错误号

消息正文

WME1034

方法“{0}”的签名中具有类型为“{1}”、下限非零的数组。Windows 运行时方法签名中的数组的下限必须为零。

WME1035

方法“{0}”的签名中具有“{1}”类型的多维数组。Windows 运行时方法签名中的数组必须是一维数组。

WME1036

方法“{0}”的签名中具有“{1}”类型的嵌套数组。无法嵌套 Windows 运行时方法签名中的数组。

数组参数必须指定数组内容是否可读或可写

在 Windows 运行时中,参数必须为只读或只写。 不能将参数标记为 ref(在 Visual Basic 中为没有 OutAttribute 特性的 ByRef)。 这适用于数组内容,因此数组参数必须指示数组内容是只读的还是只写的。 out 参数的方向很清晰(在 Visual Basic 中为具有 OutAttribute 特性的 ByRef 参数),但必须标记按值传递的数组参数(在 Visual Basic 中为 ByVal)。 请参见向 Windows 运行时组件传递数组

错误号

消息正文

WME1101

方法“{0}”具有参数“{1}”,它是数组并且同时具有 {2} 和 {3}。 在 Windows 运行时中,内容数组参数必须可读或可写。 请从“{1}”中删除其中一个特性。

WME1102

方法“{0}”具有输出参数“{1}”,它是数组但具有 {2}。 在 Windows 运行时中,输出数组的内容必须可写。 请从“{1}”中删除该特性。

WME1103

方法“{0}”具有参数“{1}”,该参数是一个数组并包含 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute。 在 Windows 运行时中,数组参数必须具有 {2} 或 {3}。 请删除这些特性或在必要时将其替换为适当的 Windows 运行时特性。

WME1104

方法“{0}”具有参数“{1}”,该参数不是数组,并且具有 {2} 或 {3}。 Windows 运行时不支持用 {2} 或 {3} 标记非数组参数。

WME1105

方法“{0}”具有参数“{1}”,该参数具有 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute。 Windows 运行时不支持用 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute 标记参数。 请考虑删除 System.Runtime.InteropServices.InAttribute 并改为将 System.Runtime.InteropServices.OutAttribute 替换为“out”修饰符。

方法“{0}”具有参数“{1}”,该参数具有 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute。 Windows 运行时仅支持用 System.Runtime.InteropServices.OutAttribute 标记 ByRef 参数,不支持这些特性的其他用法。

WME1106

方法“{0}”具有作为数组的参数“{1}”。 在 Windows 运行时中,数组参数的内容必须可读或可写。 请将 {2} 或 {3} 应用于“{1}”。

具有名为“value”的参数的成员

在 Windows 运行时 中,将返回值视为输出参数,并且这些参数的名称必须是唯一的。 默认情况下,Winmdexp.exe 为返回值指定名称“value”。 如果您的方法有一个名为“value”的参数,则会出现错误 WME1092。 可通过两种方式更正这种情况:

  • 为参数给定“value”之外的名称(在属性访问器中,给定“returnValue”之外的名称)。

  • 使用 ReturnValueNameAttribute 特性更改返回值的名称,如下所示:

    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.WindowsRuntime;
    
    [return: ReturnValueName("average")]
    public int GetAverage(out int lowValue, out int highValue)
    
    Imports System.Runtime.InteropServices
    Imports System.Runtime.InteropServices.WindowsRuntime
    
    Public Function GetAverage(<Out> ByRef lowValue As Integer, _
    <Out> ByRef highValue As Integer) As <ReturnValueName("average")> String
    

    备注

    如果更改返回值的名称,并且新名称与另一个参数的名称冲突,则会出现错误 WME1091。

JavaScript 代码可以按名称访问方法的输出参数,包括返回值。 有关示例,请参见 ReturnValueNameAttribute 特性。

错误号

消息正文

WME1091

方法“{0}”具有名为“{1}”的返回值,该名称与参数名称相同。 Windows 运行时方法参数和返回值必须具有唯一的名称。

WME1092

方法“{0}”具有名为“{1}”的参数,它与默认返回值名称相同。 请考虑为该参数使用其他名称或者使用 System.Runtime.InteropServices.WindowsRuntime.ReturnValueNameAttribute 来显式指定返回值的名称。

说明说明
对于属性访问器而言,默认名称为“returnValue”;对于所有其他方法,默认名称为“value”。

请参见

参考

Winmdexp.exe(Windows 运行时元数据导出工具)

概念

用 C# 和 Visual Basic 创建 Windows 运行时组件