سؤال

I'm writing a C# COM class using .NET 2.0 to implemented the IActiveScriptParse32 interface. When generating the TLB file using RegAsm.exe the interface methods containing EXCEPINFO structures are not exported. Why is RegAsm.exe not exporting the EXCEPINFO structure?

Interface and class declaration:

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 generates this warning:

Type library exporter warning processing 'ScriptEngine.IActiveScriptParse32. ParseScriptText(exceptionInfo), MyScriptParser'. Warning: Non COM visible value type 'System.Runtime.InteropServices.ComTypes.EXCEPINFO' is being referenced either from the type currently being exported or from one of its base types.

And generates a .tlb file with this declaration:

[
  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();
};
هل كانت مفيدة؟

المحلول

It is just like it says, the ComTypes.EXCEPINFO structure doesn't have the [ComVisible(true)] attribute. This was intentional. Note that this is only a warning, not an error.

It was intentional because the type library you create from your [ComVisible] C# code will always include stdole2.tlb. Which is a standard type library that declares all the common Automation types, like IDispatch and the structures it uses.

This is something you can see with Oleview.exe. Run it from the Visual Studio Command Prompt, use File + View Typelib and select your type library. Use Tlbexp.exe if you don't have it yet. You'll see the IDL that was decompiled from the type library, it has this near the top:

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

Now use File + View Typelib and select c:\windows\system32\stdole2.tlb. You'll see EXCEPINFO declared there.

Or in other words, whatever tool reads your type library will always have a declaration for EXCEPINFO. Regasm.exe just isn't smart enough to realize that, it doesn't look at imported type libraries.

Technically you can suppress the warning by adding a reference to "stdole", you'll see it on the .NET tab. And use stdole.EXCEPINFO in your code instead. This will put the definition of EXCEPINFO in your type library. Not so sure what will happen in the tool you use that reads the type library when it sees two definitions for EXCEPINFO so it's better to just not do that. Just ignore the warning.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top