Using registration free com in a .NET app - c#

I'm trying to use a 3rd party COM DLL (I don't believe its a .NET component) from a .NET service without registering the COM DLL but I'm having no luck so far.
I've copied the manifest files from here (http://stackoverflow.com/questions/465882/generate-manifest-files-for-registration-free-com) to use as a starting point (I generated the COM DLL manifest using the referenced mt.exe/regsvr42.exe). However all I get is the following error:
Exception: System.InvalidCastException
Message: Unable to cast COM object of type 'LOGICLib.LogicClass' to interface type 'LOGICLib.ILogic'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAA3E8FB4}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
Source: Interop.LOGICLib
at LOGICLib.LogicSecuredClass.Connect(String IP, UInt16 Value, Int32& Result)
at My.Server.MyAssembly.Loader.Connect() in D:\MyProject\Source\Server\MyAssembly\Loader.cs:line 461
The application manifest is named after the exe that starts the service - I've also tried naming it after the assembly that calls the COM DLL. I've tried starting on the command line and via Visual Studio's debugger. I've also tried using the Interop file supplied by the third party and generating my own.
(Note - I've only tested under Windows XP so far.)
I've spent two days on this now and have not progressed at all. Any ideas what I may have missed?

The application manifest is named after the exe that starts the service
Yes, this does not work. Windows always looks for a manifest in the EXE itself, embedded as an unmanaged resource. Only when it cannot find one in there will it look for a .manifest file on disk. Problem is, a managed program built with VS2008 and up already has a manifest. The default one says "I'm Vista aware" only.
You can verify this for yourself by using File + Open + File and selecting your EXE. Open the RT_MANIFEST node and double-click resource 1. If you don't see your reg-free COM manifest entries there then it isn't going to work.
To fix, use Project + Add New Item and select the Application Manifest File item template. You'll get the boilerplate manifest, copy and paste your regfree COM entries in there.

Well, from the exception, you're getting a cast error when trying to cast an object of type LogicClass to an interface type of ILogic. Looks like LogicClass doesn't implement ILogic.
You didn't supply what the DLL is or where you got it, so you're best bet is to look at the documentation for the library you're trying to use. Just a wild guess, but it looks like you're implementing it incorrectly.

Related

c# Windows Application failed to run on another computer

I have created an new C# windows forms application. I have added COM Reference "Microsoft Excel 15.0 Object Library" to my project. This project is for importing excel data to the dataset. I have done it. I works fine in my computer. If i run the exe file on another computer it showing error like below.
ERROR:
Unable to cast COM object of type
Microsoft.Office.Interop.Excel.ApplicationClass’ to interface type
‘Microsoft.Office.Interop.Excel._Application’” This operation failed
because the QueryInterface call on the COM component for the interface
with IID '{{000208D5-0000-0000-C000-000000000046}' failed due to the
following error: Error loading type library/DLL (Exception from
HRESULT:0x80029C4A(TYPE_E_CANTLOADLIBRARY)).
COM components are not my specialty, and I do not use them too often. But I will tell you what I have experienced before. Please note that I experienced this about 6 months ago and the circumstances were far from ideal at my work place.
In order to use a/some COM component(s) you also need to have it's dependency installed on the target computer (in this case Excel/Office). Have you checked if the target computer has Excel installed on it?
If not, you can use an OLEDB connection to read Excel files. I don't remember how this is done specifically.
Maybe this can help in some way to read Excel files using OLEDB: http://www.codeproject.com/Tips/705470/Read-and-Write-Excel-Documents-Using-OLEDB
In your proyect references, try to set Copy Local = true in your dll
If you are working on a 64 bit development environment, try explicitly defining the use of non 32 bit version of the library. For doing so in visual studio, tick and then untick the box "Prefer 32-bit" in the build section of the project configuration, which will add <Prefer32Bit>false</Prefer32Bit> in the .csproj file.

Call .TLB COM Library from C#

I have an old .TLB file which is called 'GrpSvr.tlb', it contains a class called GrpCall. I have registered the .tlb on my Win7 x64 machine using regtlibv12.exe which worked correctly. I want to invoke the methods withing this library from C#, so first I tried:
Type objectType = System.Type.GetTypeFromProgID("GrpSvr.GrpCall");
dynamic thirdPartyDLLObject = System.Activator.CreateInstance(objectType);
but this returns null for objectType.
Question 1. can I invoke my .TLB file this way and what I am I doing wrong in this case?
Moving away from this method I then decided to follow
Import TLB into C#
which describes how to create a C# DLL using MSs Type Library Importer. I followed this and created GrouperServer.dll from GrpSrv.tlb using the command:
C:\Program Files (x86)\Microsoft Visual Studio 12.0>tlbimp F:\Groupers\DRGROUP\GrpSvr.tlb /out:C:\GrouperServer.dll /nam
espace:GrouperServer
Microsoft (R) .NET Framework Type Library to Assembly Converter 4.0.30319.33440
Copyright (C) Microsoft Corporation. All rights reserved.
TlbImp : Type library imported to C:\GrouperServer.dll
I then imported this DLL into my C# project (and set Embed interop Types = false following this answer) and attempted to invoke the class via
GrouperServer.GrpCallClass grouperServer = new GrouperServer.GrpCallClass();
but this does not work and at run-time I get the following error:
A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in DrGroupIN.exe
Additional information: Retrieving the COM class factory for component with CLSID {FFB54BC4-B15E-11D1-99BC-0000E803C444} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
Following the advice given in
Retrieving the COM class factory for component with CLSID {XXXX} failed due to the following error: 80040154
I then set the project to target x86, but this does not help in this case.
Question 2: Why is this error being thrown and how can I resolve it?
Yeah, you are doing this wrong. A type library is not a COM server, using regtlibv12.exe is never necessary. You'll need to read the exception for what it is trying to tell you, as tens of thousands of Google hits do, the COM server is not registered.
A COM server is executable code, usually stored in a .dll. Sometimes an .ocx or an .exe. An installation step is required to register that file so that COM can find it back later when a program tries to create a COM object that the server implements. The Regsvr32.exe utility is a very common way to do that, but you should always use the installer provided by the vendor or author. Which ensures that the executable file(s) are copied onto your machine and writes the registry entries. Including the ones for the type library. The exception tells you that this wasn't done, COM cannot find the registry entry that tells it where the file is stored.
A .tlb file only describes the COM component, it tells a compiler what the declarations looks like. Helping the compiler to generate correct code to use the component and telling you when your code is wrong. It is metadata, very similar to the metadata that's present in a .NET assembly that describes the .NET types that are implemented by the assembly. It is usually embedded in the DLL or EXE as a resource, much like metadata is embedded in a .NET assembly. You can look at it with OleView.exe, File + View Typelib. Also used by Tlbimp.exe, a .NET utility that converts a type library to a .NET interop assembly, converting the declarations into a format that the CLR can easily understand.
Can't help you find the correct installer, it isn't anything standard.
Put GrpSvr.Dll and its dependencies under the exe folder, and try again. The error is because it can not the find the GrpSvr.Dll based on the GUID in the registry.
Or you can search the registry with that GUID, you will find an entry which specify where the DLL is.
One tool to debug this kind error is the process monitor in the system internal kit, the log will give you a great detail on how the exe is searching registry and files, from the log, you should find the missing parts.

Unable to find security.dll library on class library application

I trying to use ssl connection on class library application but i tried to authenticate
as a client to server i got following error message.
"Unable to find an entry point named 'EnumerateSecurityPackagesW' in DLL 'security.dll'."
Have any body experience about this?
Security.dll is also the same name for the Windows DLL containing the SSPI implementation, which is used for authentication. When loading DLLs, the local bin directory will be checked before the Windows directory. As a result, your System.dll is being loaded instead of the SSPI System.dll.
So if in certain situations your custom Security.dll is loaded before
c:\winnt\system32\security.dll then LoadLibrary thinks it has the dll
already loaded (since it's just a Win32 Dll, only name matter, NOT version
information). But as we know this is not the correct dll and hence the
problem.
The workaround is to change the dll name.

Configure .NET-Based Components for Registration-Free Activation

I've been trying to get a registration-free .NET based COM DLL to work, but without success.
In Visual Studio 2008 I added a new C# class library.
I enabled the 'make assembly COM-visible' and 'register for COM interop' options.
I added a public interface and class with some functions.
I added a manifest dependency to my C++ client application: #pragma comment(linker,"/manifestdependency ...
But when I start my application I get 'the application has failed to start because the application configuration is incorrect'.
I've used Microsoft's mt tool to extract the manifest files of both the C++ client application and the C# COM DLL and the information in both is the same (the dependentAssembly in the C++ manifest file contains the same name and version as the assemblyIdentity in the COM manifest file).
I've also tried the approach described on http://msdn.microsoft.com/en-us/library/eew13bza.aspx but with similar results.
Similarly I tried to add a reference to my COM project in 'Framework and References' of my C++ client application. The information on that property page looked promising (it shows options like 'copy local', 'copy dependencies', etc and properties like the 'assemblyIdentity'), but Visual Studio neither copies the DLLs nor adds a dependency to the manifest file automatically.
Note that the 'registered variant' works fine.
Anyone have any ideas of what I'm doing wrong?
Update:
When I create a simple C++ DLL and embed a manifest with the same name and version of my .NET COM DLL (same assemblyIdentity) my application starts up fine. So the problem lies with the manifest file of my .NET COM DLL.
I can successfully extract the manifest from the DLL with mt -managedassemblyname:... and then embed the same manifest with mt -outputresource:..., but this also doesn't cause Windows to successfully resolve the dependency.
I found the steps needed to get registration-free .NET COM interop working myself :-)
Run: mt -managedassemblyname:"myDll.dll" -out:"myDll.manifest"
Clean manifest (see format at http://msdn.microsoft.com/en-us/library/eew13bza.aspx). Mainly I needed to remove all tags except for assemblyIdentity, clrClass and file (and specifically remove the runtime, mvid and dependency tags).
Run mt -outputresource:"myDll.dll" -manifest "myDll.manifest". Basically this adds the modified manifest as a resource to the DLL. Note that this is apparently not the same manifest (location)! If I reextract the manifest with the managedassemblyname option I still get the 'old' manifest. If I extract it with the inputresource option I get the new one.
I pretty much found this all thanks to Windows Vista. Unlike my Windows XP it contains a tool called sxstrace that gives rather detailed information about the problems with side-by-side execution.
When I did this, I started with a very simple, basic component to get the COM stuff sorted. Also I used a script client in the initial development.
I did not use Visual Studio, but instead a text editor for the .NET code. I inserted the GUIDs for the assembly and for the Interfaces, and marked the interfaces for AutoDispatch.
using System;
using Interop=System.Runtime.InteropServices;
namespace Whatever
{
[Interop.Guid("xxxxxxxx-9120-4283-b972-changethis05")]
[Interop.ComVisible(true)]
[Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
public partial class MyClass :
...
}
I made sure my class had a default (no-arguments) constructor.
I ran regasm /codebase by hand, from the command line, specifying the .NET assembly.
I hand-coded the javascript to instantiate the object.
When things were confusing, I checked the ProgId with OleView.exe.
Once you have the very basic stuff working, add complexity gradually, until you get the working solution.
You can also use the approach from the other direction; from the client. .NET Assemblies like System.Random are marked for COM interop when you install .NET, so you can use them to verify that your approach in C++ is correct. Instantiating a System.Random ProgId is something like the "hello, World" of C++-to-.NET-via-COM. If that succeeds, then you know the basic approach in C++ is sound.

Interop.MSXML2 throwing exceptions because its not registered BUT IT WONT REGISTER!

Ok, this line of code:
XMLHTTP40 http = new XMLHTTP40();
Throws a System.Runtime.InteropServices.COMException and complains that:
Retrieving the COM class factory for component with CLSID {88D969C5-F192-11D4-A65F-0040963251E5} failed due to the following error: 80040154.
I have googled that and I guess the DLL needs to be registered because its a COM DLL. That's fine, but when I try to register it I get this error:
C:\some\directory\path\etc\Interop.MSXML2.dll was loaded, but the DllRegisterServer entry point was not found.This file can not be registered.
Apparently this is working on another guys box (he wrote the code, so yeah.. :P). This COM object does not show up in my list of available COM references so I just reference the DLL which is sitting in the bin\Debug directory of the project. When I add the reference to this DLL to my project, I get access to all of the symbols in VisualStudio. I'm wondering, is there something that I can install that would register the DLL and have it show up in my list of COM objects that I can reference? I installed what I thought was the MSXML 4.0 library but when I looked in the directory there wasn't anything in there.
Any ideas?
You need to actually have MSXML4 installed on your box for it to work. THe interop dll doesn't contain any runtime code it only helps .NET talk to MSXML4.
However why would you not use the System.Xml namespace instead of using a COM component?
You need to register (regsvr32) msxml4.dll, not the interop assembly. msxml4.dll is the COM server.

Categories

Resources