1

我正在使用 .NET 2.0 编写一个 C# COM 类来实现IActiveScriptParse32接口。使用 RegAsm.exe 生成 TLB 文件时,不会导出包含 EXCEPINFO 结构的接口方法。为什么 RegAsm.exe 不导出 EXCEPINFO 结构?

接口和类声明:

using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;        

namespace ScriptEngine
{
    [Guid("BB1A2AE2-A4F9-11cf-8F20-00805F2CD064")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IActiveScriptParse32
    {
        void InitNew();
        void AddScriptlet([MarshalAs(UnmanagedType.LPWStr)] string defaultName, 
                          [MarshalAs(UnmanagedType.LPWStr)] string code, 
                          [MarshalAs(UnmanagedType.LPWStr)] string itemName, 
                          [MarshalAs(UnmanagedType.LPWStr)] string subItemName,
                          [MarshalAs(UnmanagedType.LPWStr)] string eventName, 
                          [MarshalAs(UnmanagedType.LPWStr)] string delimiter, 
                          IntPtr sourceContextCookie, 
                          uint startingLineNumber, 
                          ScriptTextFlags flags, 
                          [MarshalAs(UnmanagedType.BStr)] out string name,
                          out ComTypes.EXCEPINFO exceptionInfo);
        void ParseScriptText([MarshalAs(UnmanagedType.LPWStr)] string code, 
                             [MarshalAs(UnmanagedType.LPWStr)] string itemName, 
                             [MarshalAs(UnmanagedType.IUnknown)] object context, 
                             [MarshalAs(UnmanagedType.LPWStr)] string delimiter,
                             IntPtr sourceContextCookie, 
                             uint startingLineNumber, 
                             ScriptTextFlags flags, 
                             out object result, 
                             out ComTypes.EXCEPINFO exceptionInfo);
    }


    [ComVisible(true)]
    [Guid("70C3474B-CFE3-4CBB-89F3-E9C70386BCB5")]
    public class MyScriptParser : IActiveScriptParse32
    {
        // Other interface methods

        public void ParseScriptText(string code, string itemName, object context, string delimiter, IntPtr sourceContextCookie, uint startingLineNumber, ScriptTextFlags flags, out object result, out ComTypes.EXCEPINFO exceptionInfo)
        {
            //Code
        }
    }
}

RegAsm.exe 生成此警告:

类型库导出器警告处理 'ScriptEngine.IActiveScriptParse32. ParseScriptText(异常信息),MyScriptParser'。警告:非 COM 可见值类型“System.Runtime.InteropServices.ComTypes.EXCEPINFO”被当前导出的类型或其基类型之一引用。

并使用此声明生成一个 .tlb 文件:

[
  odl,
  uuid(BB1A2AE2-A4F9-11CF-8F20-00805F2CD064),
  version(1.0),
  oleautomation,
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ScriptEngine.IActiveScriptParse32")
]
interface IActiveScriptParse32 : IUnknown {
    HRESULT _stdcall InitNew();
};
4

1 回答 1

1

就像它说的那样, ComTypes.EXCEPINFO 结构没有 [ComVisible(true)] 属性。这是故意的。请注意,这只是一个警告,而不是错误。

这是有意的,因为您从 [ComVisible] C# 代码创建的类型库将始终包含 stdole2.tlb。这是一个标准类型库,它声明了所有常见的自动化类型,如 IDispatch 及其使用的结构。

这是您可以通过 Oleview.exe 看到的内容。从 Visual Studio 命令提示符运行它,使用 File + View Typelib 并选择您的类型库。如果您还没有 Tlbexp.exe,请使用它。你会看到从类型库中反编译的 IDL,它在顶部附近有这个:

// TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");

现在使用 File + View Typelib 并选择 c:\windows\system32\stdole2.tlb。你会看到 EXCEPINFO 在那里声明。

或者换句话说,任何读取你的类型库的工具都会有一个 EXCEPINFO 的声明。Regasm.exe 只是不够聪明,无法意识到这一点,它不查看导入的类型库。

从技术上讲,您可以通过添加对“stdole”的引用来抑制警告,您将在 .NET 选项卡上看到它。并stdole.EXCEPINFO在您的代码中使用。这会将 EXCEPINFO 的定义放入您的类型库中。不太确定当您使用的读取类型库的工具看到EXCEPINFO 的两个定义时会发生什么,所以最好不要这样做。只是忽略警告。

于 2013-07-24T13:35:14.637 回答