C# ActiveX error during creation - c#

I've faced with following problem:
I have an ActiveX Control , on dev machine it is working as expected ,
when trying to create it on other machine I am getting the following error
Error: The system cannot find the file specified.
I am using following line to create it:
var activeX = new ActiveXObject("ScannerViewerControl.ScannerViewer");
I've used installshield for deployment , and marked .NET Com Interop.
I am able to find in registry path to the .dll under HKEY_CLASSES_ROOT.
What am I missing ???

You are probably missing a dependency for the active-x DLL on the client machine. Depending on what version of VS you have installed, you might have a tool called depends, which you can point at a DLL and see the dependencies that are required.

Related

BadImageFormatException Could not load file or assembly ... An attempt was made to load a program with an incorrect format

I have .NET 5 project which includes C++/CLI DLL, which includes C++ DLL, which includes opencascade DLLs. All these projects are built for the x64 platform. I've published this solution to my local folder and then set up IIS server everything works fine. But when I've tried to upload my project to two different hostings (https://www.smarterasp.net/ and azure) I've got this error. Project crashes when it starts use C++/CLI dll(using namespace C++/CLI). I've also set up x64 platform in azure portal.
I would appreciate any help.
Thank you Joe. Posting your suggestion as an answer to help other community members.
Project crashes because of missing DLL. Run the app and get the error.
Go to the Windows Event Viewer (Start Menu and type "Event"). In the EventViewer, under Windows Logs >> Application, you might see an error message regarding the failure. If the error is a missing DLL, it will typically tell you the name of the DLL as well.
You can refer to Could not load file or assembly ... An attempt was made to load a program with an incorrect format (System.BadImageFormatException), Troubleshooting BadImageFormatException and System.BadImageFormatException An attempt was made to load a program with an incorrect format

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.

Howto successfully register certadm.dll in order to be able to use ICertView2 in C# Code

Motivation:
I want be able to retrieve and view Certificates from a Windows CA on a local Machine. I don't want to access the Browser-Keystores of the Machine, but the Windows CA (Windows Certifcate Authority (Service)).
I want to to do this in C#-Code.
My Investigation so far:
I found several Examples that are using the following line:
ICertView2 certView = new CERTADMINLib.CCertView();
...
I think i'm able to use this line and the ICertView2 Structure, i reached my Goal.
If a write this Line into my C#-Code in Visual Studio, it says to me, that it don't know ICertView2 and CERTADMINLib.
So if searched the Web again and found out the i need to import a Reference. I need the COM Library certadmin.dll, that fortunately exists in my C:\Windows\System32 Folder.
So i tried to add the Reference over the Solutionexplorer->Project->References->Add Reference->COM. But it is not listed there, only a similar looking Library called "CertCli 1.0 Type Library". I added this and also was able to type an
using CERTCLIENTLib;
but unfortuneatly, the needed "ICertView2" Class is not in there.
If i type
using CERTADMINLib;
that should be typed in order to be able to use the ICertView2, Visual Studio says to me, that it also don't know "CERTADMINLib".
Further i found hints on the net, that one need to register the certadm.dll beforehand, in order to make it available in Visual Studio. I tried to register the dll-File, but it doesn't work.
If i invoke the following Command:
C:\Windows\System32>regsvr32.exe C:\Windows\System32\certadm.dll
and get a Dialogbox telling me the following:
'Error while loading the Module "C:\Windows\System32\certadm.dll". ... The specified Module could not be found.'
The Version of certadm.dll ist "5.2.3790.3959".
I'm using "Windows 7 Enterpise SP1".
Can you tell me, how i'm able to register and futher make the appropriate Reference available in Visual Studio?
If i've forgotten further Information, please let me know, so i can add them.
Microsoft changed much from XP to Win7. To be able to reference it you will have to tlbimp certadm.dll. Tlbimp.exe can be found in your .NET SDK's and such. Then you will have to import this library in your .NET solution.
Although i have to warn you, i have not mangaged to get any code working in Win7 that works in XP.
You can also look at this link:
http://blogs.msdn.com/b/alejacma/archive/2012/04/04/how-to-get-info-from-client-certificates-issued-by-a-ca-c-vs-2010.aspx

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.

Categories

Resources