我正在使用.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();
};
答案 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的两个定义时会读取类型库会发生什么,所以最好不要这样做。只需忽略警告。