I was in the process of adding a reference to a dll when I noticed that the vast majority instances of the Microsoft namespace has a uppercase M and on rare occasions they have a lower case m.
Is there a reason or any logic for this?
Does anyone know the reasoning for this decision by Microsoft?
Those entries you pointed out are not normal .NET framework assemblies. And they are auto-generated by tooling. Two good reasons they don't follow .NET framework naming conventions. They are PIAs, Primary Interop Assemblies. They contain the declarations retrieved from a COM component's type library, converted into .NET metadata to make it easy for the CLR to interop with the COM component. The types in these PIAs have the [ComImport] attribute.
Tlbimp.exe is the tool used to auto-generate these assemblies, the /primary command line option generates a PIA. The ones you got from Microsoft are slightly different from the ones you'll get when you run Tlbimp.exe yourself. For one, Microsoft includes a version resource in the assembly. For another, the names for these PIAs are not the default name that Tlbimp.exe generates. So you are seeing what the build engineer at Microsoft typed for the /out command line option. Clearly he's not paying much attention to casing.
Microsoft.msxml is the PIA for c:\windows\system32\msxml3.dll, very commonly used in older code to read and write XML documents. Microsoft.mshtml is the PIA for c:\windows\system32\mshtml.tlb, the type library for the DOM interface supported by Internet Explorer and one you'll need when you want to dig through the HTML elements of a web page. You can look at these type libraries in their "native" format with the Oleview.exe tool, File + View Typelib. What you'll see otherwise looks very similar to what you'll see with Object Browser, except that they are expressed in IDL, Interface Description Language, the language that was originally used to generate these type libraries.
PIAs are mostly an historical artifact, the Embed Interop Type feature available since .NET 4 made them unnecessary.
Related
Since version 3.0, .NET installs a bunch of different 'reference assemblies' under C:\Program Files\Reference Assemblies\Microsoft...., to support different profiles (say .NET 3.5 client profile, Silverlight profile). Each of these is a proper .NET assembly that contains only metadata - no IL code - and each assembly is marked with the ReferenceAssemblyAttribute. The metadata is restricted to those types and member available under the applicable profile - that's how intellisense shows a restricted set of types and members. The reference assemblies are not used at runtime.
I learnt a bit about it from this blog post.
I'd like to create and use such a reference assembly for my library.
How do I create a metadata-only assembly - is there some compiler flag or ildasm post-processor?
Are there attributes that control which types are exported to different 'profiles'?
How does the reference assembly resolution at runtime - if I had the reference assembly present in my application directory instead of the 'real' assembly, and not in the GAC at all, would probing continue and my AssemblyResolve event fire so that I can supply the actual assembly at runtime?
Any ideas or pointers to where I could learn more about this would be greatly appreciated.
Update: Looking around a bit, I see the .NET 3.0 'reference assemblies' do seem to have some code, and the Reference Assembly attribute was only added in .NET 4.0. So the behaviour might have changed a bit with the new runtime.
Why? For my Excel-DNA ( http://exceldna.codeplex.com ) add-in library, I create single-file .xll add-in by packing the referenced assemblies into the .xll file as resources. The packed assemblies include the user's add-in code, as well as the Excel-DNA managed library (which might be referenced by the user's assembly).
It sounds rather complicated, but works wonderfully well most of the time - the add-in is a single small file, so no installation of distribution issues. I run into (not unexpected) problems because of different versions - if there is an old version of the Excel-DNA managed library as a file, the runtime will load that instead of the packed one (I never get a chance to interfere with the loading).
I hope to make a reference assembly for my Excel-DNA managed part that users can point to when compiling their add-ins. But if they mistakenly have a version of this assembly at runtime, the runtime should fail to load it, and give me a chance to load the real assembly from resources.
To create a reference assembly, you would add this line to your AssemblyInfo.cs file:
[assembly: ReferenceAssembly]
To load others, you can reference them as usual from your VisualStudio project references, or dynamically at runtime using:
Assembly.ReflectionOnlyLoad()
or
Assembly.ReflectionOnlyLoadFrom()
If you have added a reference to a metadata/reference assembly using VisualStudio, then intellisense and building your project will work just fine, however if you try to execute your application against one, you will get an error:
System.BadImageFormatException: Cannot load a reference assembly for execution.
So the expectation is that at runtime you would substitute in a real assembly that has the same metadata signature.
If you have loaded an assembly dynamically with Assembly.ReflectionOnlyLoad() then you can only do all the reflection operations against it (read the types, methods, properties, attributes, etc, but can not dynamically invoke any of them).
I am curious as to what your use case is for creating a metadata-only assembly. I've never had to do that before, and would love to know if you have found some interesting use for them...
If you are still interested in this possibility, I've made a fork of the il-repack project based on Mono.Cecil which accepts a "/meta" command line argument to generate a metadata only assembly for the public and protected types.
https://github.com/KarimLUCCIN/il-repack/tree/xna
(I tried it on the full XNA Framework and its working afaik ...)
Yes, this is new for .NET 4.0. I'm fairly sure this was done to avoid the nasty versioning problems in the .NET 2.0 service packs. Best example is the WaitHandle.WaitOne(int) overload, added and documented in SP2. A popular overload because it avoids having to guess at the proper value for *exitContext" in the WaitOne(int, bool) overload. Problem is, the program bombs when it is run on a version of 2.0 that's older than SP2. Not a happy diagnostic either. Isolating the reference assemblies ensures that this can't happen again.
I think those reference assemblies were created by starting from a copy of the compiled assemblies (like it was done in previous versions) and running them through a tool that strips the IL from the assembly. That tool is however not available to us, nothing in the bin/netfx 4.0 tools Windows 7.1 SDK subdirectory that could do this. Not exactly a tool that gets used often so it is probably not production quality :)
You might have luck with the Cecil Library (from Mono); I think the implementation allows ILMerge functionality, it might just as well write metadata only assemblies.
I have scanned the code base (documentation is sparse), but haven't found any obvious clues yet...
YYMV
Of course the Embed interop types feature is a great thing, but I can't get it work with me even in simple scenario, so please advice
this is the error I get when I run my project on machine which didn't have powerPoint installed on it:
My code is very simple I just create object from powerPoint, create presentation and slid write something in it.
The libraries I embed is Office and Microsoft.Office.Interop.PowerPoint
converting build configuration to x68 didn't solve it,
I am building windows application and putting the code in button click as follows:
private void button1_Click(object sender, EventArgs e)
{
var pp = new powerpoint.Application();
var oPres=pp.Presentations;
pp.Visible = Office.MsoTriState.msoTrue;
powerpoint.Presentation oPre= oPres.Add(Office.MsoTriState.msoTrue);
powerpoint.Slides oSlides = oPre.Slides;
powerpoint.Slide oSlide = oSlides.Add(1, powerpoint.PpSlideLayout.ppLayoutText);
powerpoint.Shapes oShapes = oSlide.Shapes;
powerpoint.Shape oShape = oShapes[1];
powerpoint.TextFrame oTxtFrame = oShape.TextFrame;
powerpoint.TextRange oTxtRange = oTxtFrame.TextRange;
oTxtRange.Text = "All-In-One Code Framework";
string fileName = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location) + "\\Sample1.pptx";
oPre.SaveAs(fileName,
powerpoint.PpSaveAsFileType.ppSaveAsOpenXMLPresentation,
Office.MsoTriState.msoTriStateMixed);
oPre.Close();
pp.Quit();
pp = null;
}
in the top I added
using powerpoint = Microsoft.Office.Interop.PowerPoint;
using Office = Microsoft.Office.Core;
using System.IO;
using System.Reflection;
Note: the program work fine at my end where I have office 2013 installed, but this error show up at my client pc
As already mentioned, the problem is that there is that Powerpoint is not installed on the client machine.
The powerpoint object is implemented in a COM type library and installed and registered when Powerpoint is installed. COM and .NET are totally different technologies. To use COM types from your .NET application, you don't use COM type directly but a special interop .NET assembly. This assembly doesn't contain any PPT functionality, it's just a wrapper that servers as a bridge between your .NET application and a COM type. An interop assembly does all the hard work for you and defines .NET types (from COM types) that you can use as other .NET classes, for example powerpoint.Application.
The interop assembly is just a normal .NET assembly. You can reference it as other .NET references (Embed Interop Types = false). In this case you need to distribute the interop DLL with your application. If you set Embed Interop Types = true, then the interop assembly is compiled and embedded directly to your application assembly. Moreover, only types and functions that are really used are embedded. So using this option has the advantage of optimized and single assembly.
But still, even when embedded, the interop info is just a wrapper over real COM type that must be installed on client machine. If it's not, you get the error.
See more details at https://msdn.microsoft.com/en-us/library/xwzy44e4.aspx
Your option is to force the client to install PPT or avoid Microsoft.Office.Interop.PowerPoint and use some third-party PPT library that you can distribute with your application.
"Embed interop types" does not mean "embed the Office program". You got this error for a very simple reason, Powerpoint is not installed on that machine.
I supposed that the term "interop types" could use an explanation. You automate an Office program by using COM, an interop technology that preceded .NET and has many similarities to .NET. It also has the notion of metadata, just like a .NET assembly has, the type information that a compiler uses when you add a reference to a .NET assembly. That metadata is called a "type library" in COM. The type library for Powerpoint is C:\Program Files (x86)\Microsoft Office\Office15\MSPPT.OLB for the Office 2013 version.
Type libraries are not exactly perfect, they suffer from ambiguity problems that don't matter much in an application written in C++ but do matter in .NET. So the .NET designers decided to not use a type library directly. And specified the Tlbimp.exe utility, it converts the library content to a .NET assembly. Directly usable by the CLR and managed language compilers without having to deal with the headache of interpreting the type library content.
By convention, the .NET assembly generated by Tlbimp.exe is called an "interop library". It is a one-to-one match with the type library. Most importantly in the context of this question, it only contains declarations, it does not contain executable code. The code remains in the COM component, written in a non-.NET language. Like the Office programs, written in C++.
The interop assembly is required at compile-time, the compiler uses it to know what types are implemented by the COM component so it can properly type-check the code you write and tell you when you get it wrong. It is also required at runtime, it is loaded by the CLR as soon as you use one of the COM types.
Having to deploy the interop assembly to the machine that executes your program is a burden. Not in the least because you often need a "Primary Interop Assembly", yet another mystical term that relates to solving the .NET type identity problem. A detail I'll skip here. The PIAs for Office are very large. It is often very murky exactly who is responsible for ensuring the PIAs are deployed on the machine. With programs failing when nobody takes care of it, a very common mishap.
A burden that Microsoft solved in .NET 4, two COM interface types are considered identical when they have the same [Guid], even when they came from a different assemblies. Which permitted a trick, the compiler can now copy the type declarations from the interop assembly into the output assembly. Only the ones you actually use. Solving both the deployment problem and the bulky interop library problem. You no longer need a PIA and don't have to deploy the interop assembly anymore. This is what "Embed interop types" means.
Long story short, metadata is not enough to execute code. You really do have to have the Office program installed on the target machine. And get this exact exception when it is not.
Funny how the most important information in an error message can be buried so deep its very difficult to see.
Class not Registered
This is your error. Basically the object you are trying to create does not exist or has not bee properly installed on the machine you are running your software on. Is powerpoint definitely installed?
I recently took over a project and have little VS COM experience so please forgive me if I am not asking the right questions..
I have a C++ project which generate a COM dll, lets name it abc.dll.
I have another C# project which references the COM dll, however under the references, it is pointing to Interop.abc.dll. I deleted all abc.dll within the directory and interrop.abc.dll to see how the project would react, upon starting the project, interop.abc.dll is automatically generated. This boggles my mind because I dont know how interop.abc.dll is generated.
So here are my questions:
How does the C# project reference the interop.abc.dll initially if this is generated?
How is the interop.abc.dll generated if there is no abc.dll to begin with (I havnt built it)
I played around with the project and then interop.abc.dll stopped generating and was causing errors, why is it?
COM declarations are stored in a type library. Which is very similar to .NET metadata, COM was the grand-father of .NET, metadata that tells a compiler what types are stored in an assembly. Type libraries however use a fairly awkward binary format, it is very different from .NET metadata. Different enough to make the conversion from a type library to .NET metadata non-trivial. Some constructs have no conversion at all, some are troublesome enough that you ought to know about it.
So the .NET team decided that the conversion should be a separate step, one that could display warnings, or errors, when the type library content doesn't match .NET metadata closely enough. That conversion tool is Tlbimp.exe, the type library import tool. They did add this feature to the Project + Add Reference dialog. As long as the conversion doesn't generate any warnings that this works just fine. It very often does.
So the job of Tlbimp.exe, and the IDE in the case of Add Reference, is to mechanically translate the type library content to .NET metadata content. By convention, a type library named "Foo" is converted to "Interop.Foo.dll". It doesn't have to be, just the default name. You'll end up with a .NET assembly that doesn't contain any code, just metadata. .NET types that any .NET compiler can directly consume and otherwise match the type library declarations. The [ComImport] attribute is a very important one that tells the CLR that the metadata is actually for COM types.
So this all explains bullet 1. Bullet 2 is a no-go, you really do need the type library. It is very often embedded as a resource in the unmanaged DLL, Tlbimp.exe knows how to find it. Nobody can see the errors in 3 so of course it is unguessable what the problem might be. Just keep in mind that the conversion is not always without trouble, the point of making the conversion step explicit.
I want to use MSHTML [1] to access DOM in IE, but I have just found out that it lacks querySelector and querySelectorAll methods in HTML document classes, which will otherwise be very helpful to obtain elements within a document by CSS selectors.
The only workaround I can think of for now is to do everything by executing a script, but it is awful.
Is there any MSHTML version that has the two methods (querySelector and querySelectorAll)? Is there any other libraries (hopefully, official .Net libraries by Microsoft) where the two methods or their equivalents are available?
[1] %ProgramFiles(x86)%\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll
The querySelector() method and friends are alive and well in MSHtml and the IE DOM, the problem is that the PIA that most programmers have on their machine is heavily outdated. The one registered in the GAC on my machine carries a 7.0.3300.0 version number, that dates back to 2002.
There is a workaround for that, you can generate your own interop library and avoid the one in the GAC. The trick is to intentionally generate a mismatch by creating an interop assembly without a strong name so it cannot match the one in the GAC. Be sure to do this only on VS2010 or later, you want to take advantage of the Embed Interop Types feature.
Start the Visual Studio Command Prompt and navigate to your project directory. And execute this command:
Tlbimp c:\windows\system32\mshtml.tlb
It will trundle for a handful of minutes, the type library is very large, and spit out several icky looking warnings that you can ignore. Go back to VS, remove the existing MSHTML reference and use Add Reference, Browse tab. Pick the MSHTML.dll file that was generated by Tlbimp.
Do keep in mind that you now use an interop library that is compatible with the IE version that you have on your machine. Not necessarily the version your user has, so technically it is possible for your program to fail. You'd have to be very unlucky.
Yesterday I notice the same problem, I found a solution.
The Next example code works for me:
Document.querySelectorAll("#navbar_search>a").item(0).click();
If i try to do "the same", but with this code, it fails:
HTMLDocument doc;
doc = ie.Document;
doc.querySelectorAll("#navbar_search>a").item(0).click();
I'm not a COM expert but I thing the first solution is a late binding (dependences are resolved at run-time), while the second solution is a compliler-time binding and it depends on a 'good' predefined libary and that's not the case with mshtml.
I am currently creating my own intellisense, and was slightly unsure on a point:
The VS Intellisense can look into referenced DLLs and pull out the namespaces, classes etc from it. Does it do this with reflection? What if I add a DLL made in java (if that can be done?)
for C++, does the intellisense simple scan header files you #include, and find available namespaces, classes etc from that?
I don't fully care about the exact implementation of intellisense in visual studio, but I am interested in how it obtains it's data.
Compiled .NET assemblies and Java classes contain all meta-information about classes and symbols that they define. Nothing like .h or .lib files is required to link against them. For these types of modules, significant amount information may be extracted directly from them.
I do not know if Visual Studio is using reflection to read metadata from managed assemblies, but reflection is certainly a correct mechanism to apply in this case. But also note that VS displays more information than there is contained in an assembly directly, namely, the /// doc-comments. These may come from source files in other projects in the solution, and from separate .XML files that come with assemblies.
For C and C++, the matter is different. There is little information available in a DLL alone. There are export symbols, but they do not usually signal whether a symbol is a function or just an extrn, and how many arguments and what types the function takes. C++ uses so called "mangled" names, from which some information may be gained. But most information that is available about a library is coming from header files. VS, as far as I know, parses sopurce files of projects and .h files included from code to get intellisense database. There are macros (#define's), and inline and template classes and functions that are not reflected in DLL extern symbols at all.
For both managed and unmanaged assemblies, sometimes debug information PDB files are available. Again, I am not sure, but I think VS is not using them for intellisense. This does not mean that you should not. There do contain extended information about external variables, classes, functions and methods. All in all, there is no "standard" intellisense approach, and you probably should consider using multiple sources for the symbolic source information.
Unfortunately, I do not know much about Java to give a detailed answer to that part of your question. Also, there is a popular IDE framework called Eclipse, but I have not looked under its hood. There must be some interesting parts hidden there, but do your own research.
A few useful references:
Visual Studio SDK. Even if you are not extending visual studio, you may want to read its documentation. It has a section on Intellisense. Also, look at open-source IDEs, such as Eclipse and #develop
System.Diagnostics.SymbolStore Namespace contains classes to access PDB files. In unmanaged world, use DbgHelp library, part of Windows SDK.
A utility called Depends was part of Win32 SDK, and is avalable separately now. It shows externals defined by an unmanaged DLL. This SO discussion reveals a few ways to access this information programmatically. DbgHelp contains functions to un-mangle C++ names, after you extract them from the PE export directory.