Another "Interop" question.
-
The more I work on my original idea and deeper into .NET Interop -- the more I'm confused. Maybe somebody could explain to me. Here is the scenario: 1. Suppose I want to automatically export my Assembly to TypeLibrary, so other possible COM clients could use it; 2. I'm doing the following: from inside of assembly I'm using TypeLib Converter like that: TypeLibConverter converter = new TypeLibConverter(); ConversionEventHandler eventHandler = new ConversionEventHandler(); UCOMICreateITypeLib typeLib = (UCOMICreateITypeLib)converter.ConvertAssemblyToTypeLib( GetExecutingAssembly(), TypeLibFileName, 0, eventHandler ); typeLib.SetName("SomeLib"); typeLib.SaveAllChanges(); Everything works as expected and TypeLibFileName after has all interfaces, coclasses and etc. The problem is: all types in created typelibrary that are not of Primitive Types, except System.String were changed, either to become smaller in length(example: System.Drawing.Size is now just Size) or got converted, so they don't contain "." (like System.Drawing.Point is now System_Drawing_Point). However, some of CLR types were converted to COM types, like System.Windows.Forms.Form was changed to IUnknown*. And here I'm completely confused: What get's converted and what is not? How changed names ("." - "_") are supposed to be found in refferenced type libaries? How you suppose to use those TLB files in your UNMANAGED projects if they are not complete -- by not complete I mean: there is no chance System_Drawing_Point could be found in refferenced typelibs (or maybe I'm wrong)? Is there anyway of changing that behavior? Maybe I don't understand some main principles here. Maybe Idea of typelib exporting is designed just for types you manually defined and therefore they are already COM complient. Or each of defualt Object types should be wrapped before being able to use it from COM? I thought that default dynamic CCW could be created for any Object derived .NET type -- and if so it's just typelib restriction or grammar errors i'm facing? But then, why "." was selected as name/class divider by .NET team if it's in conflict with typelib grammar? Again, waiting for some help here...
-
The more I work on my original idea and deeper into .NET Interop -- the more I'm confused. Maybe somebody could explain to me. Here is the scenario: 1. Suppose I want to automatically export my Assembly to TypeLibrary, so other possible COM clients could use it; 2. I'm doing the following: from inside of assembly I'm using TypeLib Converter like that: TypeLibConverter converter = new TypeLibConverter(); ConversionEventHandler eventHandler = new ConversionEventHandler(); UCOMICreateITypeLib typeLib = (UCOMICreateITypeLib)converter.ConvertAssemblyToTypeLib( GetExecutingAssembly(), TypeLibFileName, 0, eventHandler ); typeLib.SetName("SomeLib"); typeLib.SaveAllChanges(); Everything works as expected and TypeLibFileName after has all interfaces, coclasses and etc. The problem is: all types in created typelibrary that are not of Primitive Types, except System.String were changed, either to become smaller in length(example: System.Drawing.Size is now just Size) or got converted, so they don't contain "." (like System.Drawing.Point is now System_Drawing_Point). However, some of CLR types were converted to COM types, like System.Windows.Forms.Form was changed to IUnknown*. And here I'm completely confused: What get's converted and what is not? How changed names ("." - "_") are supposed to be found in refferenced type libaries? How you suppose to use those TLB files in your UNMANAGED projects if they are not complete -- by not complete I mean: there is no chance System_Drawing_Point could be found in refferenced typelibs (or maybe I'm wrong)? Is there anyway of changing that behavior? Maybe I don't understand some main principles here. Maybe Idea of typelib exporting is designed just for types you manually defined and therefore they are already COM complient. Or each of defualt Object types should be wrapped before being able to use it from COM? I thought that default dynamic CCW could be created for any Object derived .NET type -- and if so it's just typelib restriction or grammar errors i'm facing? But then, why "." was selected as name/class divider by .NET team if it's in conflict with typelib grammar? Again, waiting for some help here...
OK, looks like I figured that out. Not elegant, but before automatically creating typelibrary, if I create a wrapper around original .NET component, enumerate all properties/methods/events and compile this wrapper -- then I could create TypeLibrary of that wrapper, which will corresponds to TypeLibrary of original object... While creating that wrapper I'm only placing alowed automation properties/methods/events in it -- so my code looks like that for methods: foreach(MethodInfo mi in t.GetMethods()) { ParameterInfo[] pi = mi.GetParameters(); Type type = mi.ReturnType; string sType = type.ToString(); if(sType == "System.Void") // Could I determine Void without string comparison??? sType = "void"; if(sType != "void") { // I'm skipping here return types causing trouble: if(!type.IsClass && !type.IsPrimitive && !type.IsInterface) continue; // bad automation method } ........ bool bExclude = false; for(int i=0; i
-
The more I work on my original idea and deeper into .NET Interop -- the more I'm confused. Maybe somebody could explain to me. Here is the scenario: 1. Suppose I want to automatically export my Assembly to TypeLibrary, so other possible COM clients could use it; 2. I'm doing the following: from inside of assembly I'm using TypeLib Converter like that: TypeLibConverter converter = new TypeLibConverter(); ConversionEventHandler eventHandler = new ConversionEventHandler(); UCOMICreateITypeLib typeLib = (UCOMICreateITypeLib)converter.ConvertAssemblyToTypeLib( GetExecutingAssembly(), TypeLibFileName, 0, eventHandler ); typeLib.SetName("SomeLib"); typeLib.SaveAllChanges(); Everything works as expected and TypeLibFileName after has all interfaces, coclasses and etc. The problem is: all types in created typelibrary that are not of Primitive Types, except System.String were changed, either to become smaller in length(example: System.Drawing.Size is now just Size) or got converted, so they don't contain "." (like System.Drawing.Point is now System_Drawing_Point). However, some of CLR types were converted to COM types, like System.Windows.Forms.Form was changed to IUnknown*. And here I'm completely confused: What get's converted and what is not? How changed names ("." - "_") are supposed to be found in refferenced type libaries? How you suppose to use those TLB files in your UNMANAGED projects if they are not complete -- by not complete I mean: there is no chance System_Drawing_Point could be found in refferenced typelibs (or maybe I'm wrong)? Is there anyway of changing that behavior? Maybe I don't understand some main principles here. Maybe Idea of typelib exporting is designed just for types you manually defined and therefore they are already COM complient. Or each of defualt Object types should be wrapped before being able to use it from COM? I thought that default dynamic CCW could be created for any Object derived .NET type -- and if so it's just typelib restriction or grammar errors i'm facing? But then, why "." was selected as name/class divider by .NET team if it's in conflict with typelib grammar? Again, waiting for some help here...
The
TLBEXP
tool is for exporting types from a .NET assembly to COM. You should useREGASM
to register your assemblies for COM while you're developing (or tick the 'Register for COM Interop' box in the IDE), and select the appropriate option (which I currently forget) in the deployment project for the assembly. The purpose of the type library is to allow COM clients to know what classes, interfaces, methods and other types the assembly exposes. This is used by scripting engines at run-time, and VB6 at design and compile time, and also run-time if you use the VB6Object
type. The COM Callable Wrapper (CCW) is an object which the framework generates that looks like a COM object externally, with COM-compatible types. This is a stub translator which marshals the types from COM formats (e.g. BSTR) into .NET compatible types, then calls the .NET method. To go the other way, for a .NET assembly to call a COM object, the runtime generates a Runtime Callable Wrapper (RCW). This is a proxy for the COM object which again translates types from .NET to COM-compatible formats. Shameless plug: we've used this with our Meteor[^] product (a system for allowing thin-client hand-held data capture terminals to run an application on a Windows server) to allow development in VB.NET, while the server software itself is written in VB6. Most new applications we're writing are now in VB.NET. -- Mike Dimmick -
The
TLBEXP
tool is for exporting types from a .NET assembly to COM. You should useREGASM
to register your assemblies for COM while you're developing (or tick the 'Register for COM Interop' box in the IDE), and select the appropriate option (which I currently forget) in the deployment project for the assembly. The purpose of the type library is to allow COM clients to know what classes, interfaces, methods and other types the assembly exposes. This is used by scripting engines at run-time, and VB6 at design and compile time, and also run-time if you use the VB6Object
type. The COM Callable Wrapper (CCW) is an object which the framework generates that looks like a COM object externally, with COM-compatible types. This is a stub translator which marshals the types from COM formats (e.g. BSTR) into .NET compatible types, then calls the .NET method. To go the other way, for a .NET assembly to call a COM object, the runtime generates a Runtime Callable Wrapper (RCW). This is a proxy for the COM object which again translates types from .NET to COM-compatible formats. Shameless plug: we've used this with our Meteor[^] product (a system for allowing thin-client hand-held data capture terminals to run an application on a Windows server) to allow development in VB.NET, while the server software itself is written in VB6. Most new applications we're writing are now in VB.NET. -- Mike DimmickSo: what are you trying to say? My complain and the problem was very specific: and exactly: why not all CLR implemented and possibly exposed to scripting types are of Automation types? For example: System.Drawing.Size is declared as struct -- therefore it cannot possibly participate in any functions calls through Automation either as a return value and/or argument -- therefore all CLR functions that use System.Drawing.Size will be visible to COM client, however will not be accesible through Automation (I mean IDispatch access)... And it's not just Size: Have a look just in System.Drawing namespace: Point, PointF, Rectangle, RectangleF, Size, SizeF... It's alot? So, how in the world could you access them through "VB6 Object type" you are reffering? Example: How you gonna call Control.Invalidate(Rectangle) from your script if Rectangle is not of automation type???... Regards
-
The more I work on my original idea and deeper into .NET Interop -- the more I'm confused. Maybe somebody could explain to me. Here is the scenario: 1. Suppose I want to automatically export my Assembly to TypeLibrary, so other possible COM clients could use it; 2. I'm doing the following: from inside of assembly I'm using TypeLib Converter like that: TypeLibConverter converter = new TypeLibConverter(); ConversionEventHandler eventHandler = new ConversionEventHandler(); UCOMICreateITypeLib typeLib = (UCOMICreateITypeLib)converter.ConvertAssemblyToTypeLib( GetExecutingAssembly(), TypeLibFileName, 0, eventHandler ); typeLib.SetName("SomeLib"); typeLib.SaveAllChanges(); Everything works as expected and TypeLibFileName after has all interfaces, coclasses and etc. The problem is: all types in created typelibrary that are not of Primitive Types, except System.String were changed, either to become smaller in length(example: System.Drawing.Size is now just Size) or got converted, so they don't contain "." (like System.Drawing.Point is now System_Drawing_Point). However, some of CLR types were converted to COM types, like System.Windows.Forms.Form was changed to IUnknown*. And here I'm completely confused: What get's converted and what is not? How changed names ("." - "_") are supposed to be found in refferenced type libaries? How you suppose to use those TLB files in your UNMANAGED projects if they are not complete -- by not complete I mean: there is no chance System_Drawing_Point could be found in refferenced typelibs (or maybe I'm wrong)? Is there anyway of changing that behavior? Maybe I don't understand some main principles here. Maybe Idea of typelib exporting is designed just for types you manually defined and therefore they are already COM complient. Or each of defualt Object types should be wrapped before being able to use it from COM? I thought that default dynamic CCW could be created for any Object derived .NET type -- and if so it's just typelib restriction or grammar errors i'm facing? But then, why "." was selected as name/class divider by .NET team if it's in conflict with typelib grammar? Again, waiting for some help here...
igor1960 wrote: Again, waiting for some help here... Try my article: Creating a RCW for COM enabled non .NET applications[^] -Nick Parker
-
igor1960 wrote: Again, waiting for some help here... Try my article: Creating a RCW for COM enabled non .NET applications[^] -Nick Parker
-
So: what are you trying to say? My complain and the problem was very specific: and exactly: why not all CLR implemented and possibly exposed to scripting types are of Automation types? For example: System.Drawing.Size is declared as struct -- therefore it cannot possibly participate in any functions calls through Automation either as a return value and/or argument -- therefore all CLR functions that use System.Drawing.Size will be visible to COM client, however will not be accesible through Automation (I mean IDispatch access)... And it's not just Size: Have a look just in System.Drawing namespace: Point, PointF, Rectangle, RectangleF, Size, SizeF... It's alot? So, how in the world could you access them through "VB6 Object type" you are reffering? Example: How you gonna call Control.Invalidate(Rectangle) from your script if Rectangle is not of automation type???... Regards
structs are valid in COM and are defined for IDL. As far as Automation goes, they can be used. The automation rules are rarely followed anymore and rarely need to be. Microsoft doesn't even follow them in many cases, as they've defined retvals that don't follow the rules, etc. You can, in fact, reference the TLB for System.Drawing.dll in VB6 and access the
Size
,Rectangle
, etc., structures just fine.Reminiscent of my younger years...
10 LOAD "SCISSORS" 20 RUN
-
structs are valid in COM and are defined for IDL. As far as Automation goes, they can be used. The automation rules are rarely followed anymore and rarely need to be. Microsoft doesn't even follow them in many cases, as they've defined retvals that don't follow the rules, etc. You can, in fact, reference the TLB for System.Drawing.dll in VB6 and access the
Size
,Rectangle
, etc., structures just fine.Reminiscent of my younger years...
10 LOAD "SCISSORS" 20 RUN
-
How can you Invoke a method on an IDispatch if the type is a structure or isn't an automation type? What is the vt param to describe this? My understanding is that these type of operations aren't possible through IDispatch and scripting.
As I said, VB did it fine and the entire language is based on
IDispatch
. You don't use a VT enum because you don't use a VARIANT. You pass the struct back as the retval. It works fine. Most automation hosts don't care anymore and they work. Try it and find out for yourself.Reminiscent of my younger years...
10 LOAD "SCISSORS" 20 RUN
-
As I said, VB did it fine and the entire language is based on
IDispatch
. You don't use a VT enum because you don't use a VARIANT. You pass the struct back as the retval. It works fine. Most automation hosts don't care anymore and they work. Try it and find out for yourself.Reminiscent of my younger years...
10 LOAD "SCISSORS" 20 RUN
This is just one more demonstration that VB as well as .NET environment will allow you to forget the basics. So you are saying you can access and pass structures solely through IDispatch? And "you don't use VT enum"? So, you can show me how to do that in a script, late binding, without TypeLibs?... Man -- what planet are you from? "Most automation hosts don't care" -- that's really funny! Me think you are mixing dual interface support with pure IDispatch...;P