RegAsm.exe不导出EXCEPINFO结构

时间:2013-07-24 10:14:29

标签: c# com .net-2.0 com-interop

我正在使用.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(exceptionInfo)   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();
};

1 个答案:

答案 0 :(得分: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的两个定义时会读取类型库会发生什么,所以最好不要这样做。只需忽略警告。