Reading MSDN pages [duplicate] - c#

What is the necessity for the GUID attribute? why don't just let the compiler handle this automatically?!

If the compiler handled this automatically, you'd end up with one of two situations.
A new GUID every time you compiled - since GUIDs are supposed to be published, this would fail.
Collisions - if the GUID was the same every time, based on (say) a Hash of the name, multiple projects would end up using the same GUID for different purposes.
The existing approach - an explicit GUID gives developers the power to control these as required.

These are attributes that matter a great deal to COM. Which was the predecessor of .NET and had its heyday in the nineties, before Java stole the show. .NET needed to be compatible with COM to have a chance of succeeding. Or in other words, you needed to be able to write a COM server in a .NET language that a large legacy program could use.
The [ComVisible] attribute ensures that a COM client program can see and use the IEnumerable interface. Essential to allow the client program to enumerate .NET collections.
The [Guid] attribute is crucial in COM, it identifies an interface. Which is done by a guid, not a name, to ensure that it is unique across multiple applications written by different programmers. .NET has this too, but however uses a name to make it easier on humans. "System.Collections.IEnumerable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".
IEnumerable<>, the generic version, doesn't have a [Guid]. Generics are not compatible with COM. It doesn't much matter these days, not much visible COM around anymore, most of it has been wrapped by friendly .NET classes. But still very core in Windows, notably in the brand-new WinRT (aka Metro, aka Modern UI, aka UWP). You don't use that directly either, making COM somewhat like the assembly language of Windows programming.

You can do it (just omit the attribute) but then the compiler will generate a new GUID on each recompile even if the interface has not changed. That's unfortunate because the users of that interface don't know about the change and will retrieve the interface by it's old GUID and will therefore fail to retrieve it.

Sometimes you want to give certain classes or modules a unique identifier that is constant and hard coded inside your source.

To read this definition you would need to look up the meaning of each of those attributes. The first, ComVisibleAttribute, is described as this:
Controls accessibility of an individual managed type or member, or of all types within an assembly, to COM.
That tells us that ComVisible is something to do with COM, and lets us specify whether a particular type is visible to COM programs. Further down on the page is a link to more details on what the attribute is for and how its used by the type library exporter.
The second, GuidAttribute, is a bit less helpful at first:
Supplies an explicit System.Guid when an automatic GUID is undesirable
but again, you have to read the rest of the way down, and you will see another mention of the type library exporter.
Putting these two together, it starts to become clear that these two attributes control how IEnumerator is processed when exported to a type library. If you don't know what a type library is, this will probably not mean much to you. If you are not using COM interop, then those attributes can safely be ignored. If you are using COM interop, you would need to know the Guid to properly access the interface from unmanaged COM code.
Microsoft puts these on every interface definition in case you need them; part of the skill in reading the MSDN pages is to recognize this type of information and know when it isn't any use to you. Now that you know what those two attributes are for, you should be able to figure out if they are relevant to you, and ignore them otherwise.

Related

Why registering COM interfaces?

I've used COM for some years now but I keep learning new (and strange) things.
Recently I've realized that COM interfaces didn't had to be registered in the registry for components implementing them to work.
I've come to this conclusion after analysing the registry of a workstation where COM DLLs (implemented in .Net/C#) were registered with .reg files created by RegAsm because the user was not an administrator. And RegAsm only generates registry keys for COM classes and not interfaces.
If that's true my guess is that interfaces are important for early binding and have only to be present in TLB files. On the contrary registering implementations (classes) is essential because they are backed by physical code on the file-system that need to be referenced.
1) So am I crazy, missing something, or interfaces can be omitted?
2) If they can be omitted what are the consequences if any?
There are a lot things that you can't do without the interface being registered. Many of the features of COM -- marshaling, proxying, asynchronous calling -- have standard implementations that prevent you from having to roll this stuff yourself. For example, CoMarshalInterface is a standard way of taking any COM object interface and marshaling that interface into a stream so that it can be unmarshaled in another thread, process or machine. The interface information is critical in this -- without the interface metadata, the standard COM implementations of things like this won't work, as the infrastructure simply doesn't know enough about your interfaces to do what it needs to do in a generic way that works for all COM objects.
Additionally, while most automation clients (like VBA, C# and C++) can reference a type library file directly for purposes of early-binding, there are still limitations. For example, suppose you're working with a type library that contains some classes that implement interfaces from a different type library, or maybe the interfaces in the first type library accept parameters or return values that are defined by interfaces/enums/etc in another type library. In order for an automation client to work with these interfaces which contain cross-references, the cross-referenced type library must be discoverable somehow. Registration is the way this is accomplished.
Worth noting: In my experience, pretty much everything that works when a COM object is registered machine-wide (registered in HKLM) works exactly the same when registered per-user (in HKCU). This often makes COM registration more palatable in situations where machine-wide registration can't be performed (e.g. the user is not an admin). However, there are some significant gotchas, most notably https://techcommunity.microsoft.com/t5/Windows-Blog-Archive/Per-User-COM-Registrations-and-Elevated-Processes-with-UAC-on/ba-p/228531
Pretty vague, not sure I could read all the words between the bold ones. There is in general more than one way to skin this cat. COM requires using a class factory to get an object created, the generic work-horse one is CoCreateInstance(). CreateObject() is popular in scripting environments. You give it a number and it spits an interface pointer back. With the COM runtime taking care of the job to locate the executable file that contains the coclass, loading it and finding the proper class factory implementation.
Finding the executable is the tricky part, this is commonly done by info in the registry. Entered there when the component was registered. Not exclusively, a manifest can also be the source of this info. It needs to be embedded in the client app, one reason it is not a universal solution. More modern is the package manifest in a Windows Store/Phone/Universal application. Required, only very privileged components can still use the registry to let themselves be found. Microsoft components.
A completely different tack is having custom class factories. The way it is done in DirectX for example, it doesn't depend on the registry at all. You call CreateDevice() instead. Still calling this COM is a bit of a stretch, it is a more general technique called interface-based programming.
This all applies to objects, interfaces are different. You call IUnknown::QueryInterface() to obtain an interface pointer. No registration required, it is the coclass that handles it.
Nevertheless, you'll find lots and lots of registered interfaces with Regedit.exe in the HKLM\Software\Classes\Interface registry key. They take care of another COM detail, if the component does not live in the same machine or same process or the same thread as the client code then extra work must be done to get the call serialized across the machine/process/thread boundary. Same kind of thing that happens in .NET Remoting, it requires a proxy. An object that also implements the same interface but doesn't execute the method directly, passing the arguments to the stub instead so it can make the call.
Simple to do in .NET, Reflection makes it very easy. Not simple in COM, an extra component is required that knows how to serialize the arguments into an interop packet. And get the return value back the same way. Proxy/stubs are normally automatically built from the IDL. Or very common in .NET since it doesn't use IDL, you use the marshaller that digs out method details from the type library. A mechanism that's highly comparable to .NET Reflection, the type library plays the exact same role as .NET metadata does.
The ProxyStubClsId32 registry key inside the Interface key contains the CLSID of that component. You'll very commonly find {00000320-0000-0000-C000-000000000046} there, that's the system provided marshaller that uses the type library.
Regasm doesn't write the interface keys, it sets the ThreadingModel key for a .NET [ComVisible] class to "Both". So that the methods can be called both from an STA as well as an MTA thread without having to be marshaled. That's very optimistic and very rarely tested, writing thread-safe .NET code isn't that easy.
Regarding your first question, if the interface is not supposed to be used across COM contexts, or if the interface derives from IDispatch and you only use late-binding, you don't need to register it.
However, if you use early-binding, or if the interface is supposed to be used across COM contexts, you need to register it.
Just registering an interface doesn't enable marshaling, all argument types and return types must be marshalable too, i.e. not HANDLE or alike.
Regarding your second question, my hope is that you can answer yourself after reading the answer thus far. If not,
if you don't register an interface, you can't use it directly across COM contexts. If it derives from some registered interface, you can use that interface, such as the case of IDispatch-based interfaces.
However, very few interfaces are as general as IDispatch, so for any other base interface, you won't be able to use your derived interface's new methods.
In type libraries, if you don't register event dispinterfaces, then development tools (typically IDEs) won't be able to show you which events can be fired, or any event at all. The only other option is to implement the dispinterfaces by hand, if your programming language has that option, which requires documentation equivalent to the missing IDL in the first place.
One common extreme of this is to have all objects simply implement IDispatch and no other interface, but again this will hinder any effort a development tool might do towards method listing, code completion and/or argument choice (e.g. IntelliSense). Note that sometimes this is enough, such as when implementing a window.external object for IE's JScript, but it's a bit of lazyness when done in more general objects.
In general, if you're required very few extra effort to have interfaces registered, given you're already targeting COM, do so.

Using a type, without knowing about the dll

is it possible to use an interface type, that is defined in a huge external dll, without referencing that dll?
in other words, there will be one core or global dll, that references the external dll, and all the projects reference this global one, so the external dlls are hidden from the other projects.
I want to use the type in my code, while knowing only about the global AllInterfaces project.
can that work? and if so, what needs to be done for such a scenario?
Is it possible to use an interface type that is defined in a huge external dll, without referencing that dll at compile time?
Not really, no. The compiler has the reasonable expectation that the types it needs are available.
Is it possible to use an interface type that is defined in a huge external dll, without referencing that dll at runtime?
Yes. We added that feature to C# 4. The "proper" name for the feature is something like "Type Embedding with Type Equivalence", but everyone just calls it "No PIA".
The motivation for the feature is the one faced most obviously by Visual Studio Tools For Office developers. VSTO developers write C# code that customizes, say, an Excel spreadsheet with some managed code. They communicate with Excel via a managed interface, but of course Excel actually exposes a set of COM interfaces. To bridge that gap, the Office team supplies a Primary Interop Assembly, or PIA. The PIA is a huge external library that contains nothing but metadata that describes how the managed interfaces correspond to the unmanaged interfaces of the COM objects.
The problem is that the Office team does not by default install the PIA when your customer buys Office! Therefore you have to ship the PIA with your customization. And the PIA is so large, it is often many times the size of the customization, which makes your download longer. And so on; it's not an ideal situation by any means.
The No-PIA feature allows the compiler to link only the portions of the PIA you actually use into your library, so that you do not have to ship the PIA with it.
Now, you might ask "what if I have two customizations that communicate with each other, and both use the IFoo interface from a PIA that I am not shipping?" The runtime identifies types by the assembly they came from, and so the two IFoo interfaces would be considered different types, and therefore not compatible.
The "No PIA" feature takes this into account as well. It does the same trick you use in COM to solve this problem: the assembly instructs the runtime to unify all interfaces that have the same GUID into the same logical type even if they come from different assemblies. This thereby explains the requirement that every interface that you use with "no PIA" has to be marked as though it were a COM interop interface with a GUID.
On the command line, use /L instead of /R to reference an assembly as a "no PIA" assembly.
Do a web search on "no PIA" and you'll find more information on this feature.
If you want to use that interface type in your code, that interface should be visible to your code. You code won't compile.
You can write adapter interface in your global dll, for the original interface and use that every where.
It cannot be done statically but you can do it using reflection.
With C# 4 you can use the dynamic keyword.
However, I fail to see how not knowing the interface in advance is going to help you - how are you going to know which methods to call?
You are trying to fool type identity. The CLR identifies a type by these properties:
Assembly display name
[AssemblyVersion]
[AssemblyCulture]
The assembly's PublicKeyToken value
The assembly's processor architecture (implicit)
The type's namespace name
The type's name.
Faking the type namespace name and name isn't difficult, the hard thing to do is faking the assembly properties. You are dead in the water if the assembly is strong-named (non-null PublicKeyToken) or if it is stored in the GAC, you can't get the substitute loaded. Faking the culture and architecture isn't hard to do, you'll have to get the display name and version right.
And of course, you'll have to get the interface declaration exactly right. Intentionally invoking DLL Hell like this is otherwise an Extremely Bad Idea. Not in the least because you now can never get the real assembly loaded.

Attributes, just metadata or needed?

Few days ago I asked what this attribute means:
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")] public unsafe static extern bool ZeroMemory(byte* destination, int length);
I have learned that attributes are metadata but what I do not understand is - is this needed in this case? I thought metada are just that, metadata that can be ommited. Also the code seems to be running fine when I remove the attibute.
I would like to understand.
PS: Hans Passant mentioned its covered by any book about .NET Csharp..it is not, the largely used one VS 2010 from John Sharp does not cover it.
The metadata does usually have a reason and a meaning. In this particular case it tells the compiler how to bind this external method definition (e.g. to which DLL import it matches).
Other attributes control how interop is performed by the framework, yet other control how the object inspector displays data. 3rd-party attributes are also used extensively to control various behaviors, for instance for finding specific type information when performing reflection.
No, this attribute is absolutely required. It informs the CLR that what you've defined actually uses platform invokation services (or, P/Invoke) to call a function defined in unmanaged code.
Specifically, the RtlZeroMemory function, defined in the library kernel32.dll.
Without it, the compiler wouldn't know which function it was bound to, and the CLR wouldn't know which function to call at run-time.
This attribute is doing 2 things
Informs the CLR that the C method being invoked lives in kernel32.dll
Informs the CLR that the C method name is RtlZeroMemory and not ZeroMemory as it's named in code.
Yes this attribute is 100% necessary. It's a requirement for any PInvoke method to at the least name the DLL the C method lives in.
As your example shows, attributes are in fact needed in several key areas of .NET programming.
Attributes provide a model known as "Aspect-Oriented Programming" or AOP. Instead of having to write code that performs some specific task, such as serialization, DLL interop, logging, etc, you can instead simply decorate the classes or members on which you want these tasks performed with an attribute. Attributes are a special type of class, with members which can be invoked by the CLR as it runs your code, that will perform the task you wanted when you decorated the code.
You are correct in part; many attributes are intended simply to store metadata. DescriptionAttribute is a good one. However, even in this case, the attribute is important depending on how it's used. If you are decorating a member of a GUI class that you want to use in the designer, [Description()] provides valuable information to the user of the class in the designer, which may not be you. I've also seen and used many alternate uses for DescriptionAttribute; it can be applied to almost anything, so I've used it to provide "friendly names" for Enum constants, coupled with a GetDescription() extension method to grab them, when using Enums to populate drop-down lists.
So, while it's technically "metadata", an attribute's being "required" is governed by how much you want the task inherent in that attribute to be performed.
As for this particular attribute, I'm not too sure. To be honest, I've never seen it in almost a year of constant C#.
However, attributes in general can prove very useful. For instance, I was having issues with the VS2010 designer setting autocomplete properties in the wrong order, and getting run-time errors as a result. The solution was to add attributes to the autocomplete properties that prevented the designer from writing these properties to the design file, and instead setting the properties myself in the .cs file (in the proper order).
Summary: Attributes (usually) are not required, but can prove extremely useful.

What is the Guid attribute that appears above classes in C#?

I've picked up some C# code recently and one of the classes has a Guid attribute present above it. I don't understand what this is or what it's used for.
Can someone give me a rundown of what it is, or just point me in the direction of some articles that give more information about this?
Thanks!
It is the COM identifier that represents the class in question. The class is designed for COM interop.
You might want to take a look at the ComVisibleAttribute class to learn more about the ways you can make managed classes available to unmanaged code.
The [Guid] is the exact equivalent to the .NET Type.AssemblyQualifiedName. Like
System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5561934e089
With the obvious distinction that the .NET type name is easier to read by a human. It is necessary to allow a program to discover what DLL needs to be loaded to use a type. In the .NET case, the assemblies are (usually) found by enumerating the GAC. It is file based.
COM however uses the registry. After that assembly whose source code you looked at gets built and registered then you can find back the [Guid] in the registry. Fire up regedit.exe and navigate to HKLM\Software\Classes\CLSID\{guid}. You'll see the registration key values that the runtime uses to load the CLR and the assembly.
Guid (Globally unique identifier) is used to identify your component by outside world. When you write a project which is going to be used as COM (Component Object Model) you will have to give a unique name. For this reason you need to apply GUID attribute.
You can read more about it here.
GUIDAttributeClass

COM to .NET Interoperability

If you want to use a COM type in your C# code, the process is straight forward, right? You just need to use the type library importer and that's fine, but what if you don't have one and you can't take a look at the IDL file? You just have the COM DLL server.
As an example, try using the IActiveDesktop interface.
What's the approch used to solve this kind of problem?
There are two kinds of COM interfaces. The one you are familiar with are the ones that restrict themselves to a subset of the COM spec known as "OLE Automation". Also known as ActiveX before that term became associated with security disasters.
Automation compatible interfaces are easy to use from just about any language. They typically inherit from IDispatch, allowing them to be used from scripting languages. And limit themselves to using only automation compatible types for their method arguments. The simple stuff, comparable to the .NET value types, BSTR for strings, SAFEARRAY for arrays, VARIANT for untyped arguments, quite similar to .NET's System.Object.
Another feature they support well is type libraries, the equivalent of .NET metadata. Used by a compiler to know how to call the interface methods. The IDE uses a type library to automatically generate the interop library so you can directly create the wrapper class and call the methods from .NET code.
Well, that's the good news. The bad news is that there are lots of COM interfaces around that do not use the Automation restrictions. They typically inherit from IUnknown and use function arguments that don't marshal well. Like structures. One very large and visible component in Windows that is like this is the shell. Windows Explorer.
That's where IActiveDesktop fits in as well, it is a shell interface and inherits from IUnknown. It is declared in the ShlObj.h SDK header file, there is not even a IDL file for it. And consequently no way to get a type library with its definition. It uses incompatible argument types, like LPCWSTR (a raw pointer to a string) instead of BSTR. And structure pointers like LPCCOMPONENT and LPWALLPAPEROPT. The CLR interop support is powerless to marshal that properly.
Using the interface in C# is technically not impossible, but you have to redeclare the interface. Very carefully, getting it wrong is very easy to do. The fact that source code that already does this is very hard to find is a hint how difficult it is. This squarely falls in the 'not impossible, but what sane programmer wants to maintain code like this' category. The shell is the domain of unmanaged C++ code. And a crew of hardy programmers, because debugging shell extensions is quite painful.

Categories

Resources