CS1545 错误与特定的 COM 对象属性

CS1545 error with specific COM object properties

提问人:JBL 提问时间:11/14/2023 最后编辑:JBL 更新时间:11/16/2023 访问量:49

问:

我正在使用第三方库进行 COM 自动化。当尝试访问某些属性时,我需要使用而不是 .obj.get_Property()obj.Property

这似乎只发生在同时具有 getter 和 setter 的字符串类型的属性上。

我想知道为什么 C# 无法处理这些情况,以及我是否可以做些什么来解决这个问题。

编辑 - 附加信息:

  • 自动化目标应用程序附带了 .tlb 格式的类型库,Visual Studio 使用该库来生成互操作库。
  • 感兴趣的反编译互操作库如下所示:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using NS0;

namespace NS1
{
    [ComImport]
    [Guid("AAAAAAAA-BBBB-CCCC-DDDD-000000000000")]
    [TypeLibType(1234)]
    public interface SpecialDocument : Document
    {
        //...
        [DispId(1234567890)]
        new string Name
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1234567890)]
            [return: MarshalAs(UnmanagedType.BStr)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1234567890)]
            [param: In]
            [param: MarshalAs(UnmanagedType.BStr)]
            set;
        }
        //...
        [DispId(1234567891)]
        new string FullName
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1234567891)]
            [return: MarshalAs(UnmanagedType.BStr)]
            get;
        }
        //...
        [DispId(1234567892)]
        new bool IsVisible
        {
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1234567892)]
            get;
            [MethodImpl(MethodImplOptions.InternalCall)]
            [DispId(1234567892)]
            [param: In]
            set;
        }
    }
  • 在上面的代码片段中,在定义的 3 个属性中,只有 Name 必须使用 get_Nameset_Name 进行访问。其他属性可以像在 C# 中预期的那样访问。
  • NameFullName 都继承自 NS0 中定义的父类 Document,其中它们具有相同的定义。
  • 根据文档,产品的所有自动化接口都派生自 IDispatch

编辑 - 添加重现步骤:

  1. 获取 FancySoft 的许可证并安装产品。
  2. 在 VS 2022 中启动新的 .NET 4.8 控制台项目。
  3. 导入 COM 引用。
  4. 在“Main”中,使用Marshal.GetActiveObject("FancySoft.Application");
  5. 导航到 SpecialDocument 实例,并尝试读取文档的 Name 属性。
  6. CS1545系列

编辑 - 来自 的其他信息。TLB(使用 oleview.exe 提取):

// From "dispinterface Document":
[
  uuid(AAAAAAAA-BBBB-CCCC-DDDD-111111111111),
  helpcontext(0x00001111),
  dual
]
dispinterface Document {
    properties:
    methods:
        // ...
        [id(0x76543210), propget, helpcontext(0x00001234)]
        BSTR Name();
        [id(0x76543210), propput, helpcontext(0x00001234)]
        void Name([in] BSTR* rhs);
        // ...
};

// From "interface Document":
[
  odl,
  uuid(AAAAAAAA-BBBB-CCCC-DDDD-111111111111),
  helpcontext(0x00001111),
  dual,
  oleautomation
]
interface Document : BaseObject {
    // No member description for the 'Name' property.
};

// From "dispinterface BaseObject":
[
  uuid(AAAAAAAA-BBBB-CCCC-DDDD-222222222222),
  helpcontext(0x00002222),
  dual
]
dispinterface BaseObject {
    properties:
    methods:
        // ...
        [id(0x76543210), propget, helpcontext(0x00001234)]
        BSTR Name();
        [id(0x76543210), propput, helpcontext(0x00001234)]
        void Name([in] BSTR* rhs);
        // ...
};

// From "interface BaseObject":
[
  odl,
  uuid(AAAAAAAA-BBBB-CCCC-DDDD-222222222222),
  helpcontext(0x00002222),
  dual,
  oleautomation
]
interface BaseObject : BaseDispatch {
    // ...
    [id(0x76543210), propget, helpcontext(0x00001234)]
    HRESULT Name([out, retval] BSTR* oNameBSTR);
    [id(0x76543210), propput, helpcontext(0x00001234)]
    HRESULT Name([in] BSTR* oNameBSTR);
    // ...
};
C# COM 互操作

评论

0赞 Simon Mourier 11/14/2023
它取决于 COM 对象本身、它的定义方式、它是否使用 IDispatch 接口或 IUnknown 派生接口、对象是否具有类型库 (.TLB 或 .DLL 嵌入一个)与否,如果您在 C# 中手动定义接口等。如果对象难以帮助,没有细节,请提供更多细节stackoverflow.com/help/minimal-reproducible-example
0赞 JBL 11/15/2023
@SimonMourier我已经更新了我的答案。当一个人不太了解某个主题时,很难猜测什么是有用的信息与噪音(这是我在 COM 上的情况,也是我首先在这里发帖的原因)。如果您仍然缺少任何内容,请告诉我。
1赞 Simon Mourier 11/15/2023
如果可以导入 .NET 的元数据,则意味着某处存在 TLB(我们还看到生成了 TypeLibType 属性)。问题通常是 .NET 生成的代码来自 Fancysoft 供应商真正定义的内容。您能否找到 TLB(在 90% 的情况下,它嵌入在主要的 fancysoft .DLL(不管是什么)中,它也可以在 .csproj 中可见,并使用 Windows SDK (learn.microsoft.com/en-us/windows/win32/com/...) 的 OLEView 打开它,打开 .dll 或来自 Oleview 的 .tlb。
0赞 JBL 11/16/2023
谢谢@SimonMourier。如前所述,.type 库由供应商提供。我编辑了我的问题,并通过在oleview.exe中打开类型库来添加我可以找到的与Name属性相关的内容。
1赞 Simon Mourier 11/17/2023
好的,这是因为定义使用 a(指向 BSTR 的指针),而不是 .因此,get 和 set 不是,.NET 会尽其所能(即:构建两个方法)。例如,如果更改为并重新生成 TLB,则 .NET 将生成一个漂亮而舒适的属性。它有效,但它是一个笨拙的 IDL 设计。propputBSTR*BSTRcompatibleHRESULT Name([in] BSTR* oNameBSTR);HRESULT Name([in] BSTR oNameBSTR);Name {get;set;}

答: 暂无答案