2013-07-24 20 views
1

我在写一个使用.NET 2.0的C#COM类来实现IActiveScriptParse32接口。使用RegAsm.exe生成TLB文件时,不会导出包含EXCEPINFO结构的接口方法。为什么RegAsm.exe不能导出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

它就像它说,该ComTypes.EXCEPINFO结构不具有[标记有ComVisible特性(真)]属性。这是故意的。请注意,这只是一个警告,不是一个错误。

这是故意的,因为您从[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"); 

现在使用文件+查看类型库,并选择C:\ WINDOWS \ SYSTEM32 \ STDOLE2.TLB。你会在那里看到EXCEPINFO。

或换句话说,无论使用什么工具读取您的类型库将始终有一个EXCEPINFO声明。 Regasm.exe只是没有足够的智能来实现,它不看导入的类型库。

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