2013-07-24 17 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時,你使用的工具會讀取類型庫,所以最好不要這樣做。只要忽略警告即可。