i have create a c++ DLL with COM interface with Visual Studio 2013.
The DLL get's installed along with registration.
In the Ole Object Viewer, i can see typelibrary of this DLL with all
exported functions.
regsvr32 completes without any error.
Just within C# i can't use, because creation fails with error 0x80040154 -
class not found or not registered.
It is not a platform issue. The 64bit version is in system32 and the 32bit
version in syswow64 and they are registered there and typelibary information
in OLE Object Viewer confirms this.
But the class is not listed in the OLE Object Viewer tree.
Habe noe idea what's missing or wrong.
More over, i have a simliar VC++ project and this COM/DLL can be seen
in the view in the OLE Object viewer. It is compiled, linked
and installed in exactly the same manner.
I already compared all Compiler, Linker and MIDL settings, checked the .idl
file in the projects, the .rgs files... all seems to be the same, except
different names and guids.
So it is really strange: One is shown as COM object in the tree
of OLE Object viewer and can be used in C# program, the other not.
Please note: There is no compiler error in C# project using this DLL/COM.
There is a runtime error on creation 0x80040154.
Summary: i have to COM/DLL, both visual studion projects, deployed in the same
manner, the one can be seen in the OLE object tree and can be used in C#, the other not.
Are there any key points i could check and which are required for a successfull
listing as OLE COM object ?
PS: The only difference is the MSIL compiler version indicated in the type library view: The good COM/DLL has MSIL 7.xxx the bad one 8.xxx
but i don't know where at all to selected MSIL compiler. Both DLL/COM are built
by VS2013
OLE/COM Object Viewer shows the registration. When an application attempts to create an instance, there are further steps involved: registration points to server implementation, the library is loaded, class factory is located, class factory is called to created an instance. A failure in these steps results in instantiation failure nevertheless the registration itself is present and valid.
Your typical steps to troubleshoot the problems are:
Setting a break point in constructor of your COM class, in class factory construction, in DllGetClassObject exported function of your DLL, finally in its DllMain - to find out how close the system reaches trying to create an instance. Then step from there to get to the root of the problem.
Using Process Monitor to track registry/file activity around instantiation call and identify issues there (esp. if your DLL with COM server implementation is not even loaded).
If the class is not even listed in OLE/COM Object Viewer, then there is a problem even at registration stage. Your first troubleshooting attempt is to re-register manually and see if you have any registration error, or if it fixes the problem. There is a number of reasons for the registration to fail, a typical is that you have your COM class in your type library, however there is no implementation connected and referenced by OBJECT_ENTRY. With failed registration instantiation is expectedly not working because system cannot pick your implementation up and you see what you see: REGDB_E_CLASSNOTREG error code.
Found the problem: The typelibrary was not associated with object, because the typelibrary CLSID in .rgs file was different from that in .idl file, just by a space which was most likey introduced accidently.
in .rgs file:
TypeLib = s '{7DAA7049 -AAB2-4689-8635-FB6E03423F34}'
in .idl
uuid(7DAA7049-AAB2-4689-8635-FB6E03423F34),
Now i can use the DLL as COM in my C# project.
The COM/DLL was not listed in the object tree, because in the .rgs file was no name defined. This is a definition with name and this is the name of the COM/DLL in object viewer; the name follows to s which was previously empty (s'').
ForceRemove {4763F309-D922-227A-A1A8-CDFF29893BBD} = s 'myDllCom Class'
Related
I'm trying to use a 3rd party DLL (WinSCP .NET assembly) in Dolphin 6.1b2. I've registered the DLL and generated a TypeLib in Windows 7.
In Dolphin I successfully used the component wizard to generate the interfaces but when I try to register the control and TypeLib I get errors. On the registering the control I get
WinSCPnet.dll was loaded but DllRegisterServer entry point could not be found.
Does anyone have any idea why it's failing? I have also asked the author of the DLL and he's leaning toward a Dolphin problem since the registration worked in Windows.
The DLL is a .NET assembly, import the generated TLB.
Downloaded ".NET assembly/automation package" from: https://winscp.net/eng/download.php
Unpacked, registered as per included readme_automation.txt.
See also Downloading and Installing WinSCP .NET Assembly
Started fresh Dolphin, imported the .tlb, generated with WinSCP prefix (so the classes wouldn't start with _).
Opened workspace, imported the WinSCP_Constants Pool, converted start of the C# example (https://winscp.net/eng/docs/library#example):
opts := WinSCP_SessionOptions new
protocol: Protocol_Sftp;
hostName = 'example.com';
userName: 'user';
password: 'mypassword';
sshHostKeyFingerprint: 'ssh-rsa 2048 ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff';
yourself.
Got working object back ...
EDIT: Your WinSCP forums notion "in order to use it within dolphin you need to have its tools register the dll and tlib" is wrong. The COM "source" needs to be registered only once (In case of "old-school" COM server, you can either use regsvr32 or dolphin - both does the same; in case of .NET assembly you have to use the .NET incantation). Only thing really needed on dolphin side is to import previously registered library.
If there is .TLB, I'd go for .TLB, otherwise try my luck with .DLL. Sadly, for some standard COM interfaces Microsoft never made typelibs available, so it's even worse there (use C/C++, or create struct/interface tables by hand).
Edit 2 - further questions:
1) can you explain the relationship between the typelib and the library class which "i create" ( i.e. dolphin tutorial in help)
Dolphin creates smalltalk classes to mirror the COM types / structures. You use these to instantiate COM types from Smalltalk, call their methods, pass them (and also primitive types such as strings, integers, ...) as arguments and get Smalltalk types for returned values (Dolphin does all the conversions for you, so you can +- forget you are calling foreign code).
2) an example of the method you implemented mapping the library class to the winscp interface.
I implemented nothing, I just used the generated wrapper (in background, WinSCP COM object - SessionOptions - got created, and had some properties set).
basically, i just said:
var opts = new WinSCP.SessionOptions().
opts.Protocol = Protocol.Sftp;
opts.HostName = .........
Just look at WinSCP Automation documentation / examples, and then convert it to smalltalk-speak (and hopefully, it should auto-magically work ;-).
3) where are the smalltalk methods protocol:, hostName:, etc defined? i searched the image and they are not there. how did you know to use those method names?
Since SessionOptions (represented by [PREFIX]_SessionOptions class in Dolphin) is an IDispatch interface (subclass of IDispatch in Dolphin), all the method calls are dynamic in nature. You just do the right things (& catch possible failures at necessary granularity), and it will "just work (tm)".
Smalltalk sibbling is the #doesNotUnderstand: aMessage method.
The situation is that. I run Labview and from one via ActiveX pallet call my COM object method. And it works, I walk through my code with debugger.
But when I start to use (uncomment) code from side dll I see "class is not registered" error in Labview. My additional dll and its dependencies located in separate directory. So I tried to set PATH environment variable to this directory and after that run Labview. But is still doesn't work.
So the question is how to debug this situation? I looked through event logger but didn't found anything related.
P.S. I created my own synthetic application in C++ which calls the same method as Labview via COM too. And it works.
The problem was in hard defined base dll address. Labview used this address and COM dlls couldn't use that space.
I suppose report is incorrect ("class is not registered") because class is registered, but corresponding dll couldn't be loaded.
I am modifying an existing application in VB .NET.
In one routine, I have added a reference to a class in a newly-referenced class library project that is part of my solution, and now I get run-time FileNotFoundException messages when the program attempts to access this routine while debugging. The error tells me that the class can't be found, what's up with that?
To be clear: if I remove the lines of code relating to the new class, I no longer receive the exception messages. If I add them back in, here they come again!
I have referenced the class library in the project containing this routine.
The class library is building properly (other projects reference same library, and use it more extensively), and the project is referencing the class library's .dll file in my "debug" folder.
I get no errors from other routines that use this new class (thus far).
I get no errors in the Error List of the IDE.
What in the world could be happening here?
SH
This is a project reference, not a reference to an assembly (DLL), right?
Are the .NET frameworks the same?
Does the project you are referencing depend on some external assemblies not included in the other project, that might be called, producing the file not found?
I have VB6 ActiveXDLL called A.dll , I am referencing this DLL into my VB.Net Application.
Now I am calling a function of A.dll in this project. A.dll function is referring to the function of B.dll, C.dll, C.dll further referrer to Z.dll and so on.
when I am executing application it gives an error from B.dll that ActiveX component can't create an object.
My first thought would be to make sure all dlls are registered.
Assuming the ActiveX DLL is VB6 and you have access to the VB6 IDE, ensure the class's Instancing property is set to Multiuse.
Use OLE View (comes with visual studio) to browse ther TypeLib entry and check it has the correct GUID and that there is onely one registration. Can you create an object instance from the DLL with CreateObject? If not it is not registered correctly.
Also check any dependencies / references used by A.dllIf it can't find something then it's going to fail.These are the four common causes of the error:
1. You do not have a required TLB or ActiveX DLL/OCX file.
2. A TLB or ActiveX DLL/OCX needed by the project is present but not registered on your system.
3. The VB runtimes are an earlier version than the one you need to run the project.
4. A required TLB or ActiveX DLL/OCX file is corrupt.
I am trying to create an instance of a COM object. I have the class name that implements the interface and I get a CLSID by using CLSIDFromProgID(). So since I am getting a CLSID I thought everything should be fine from now on. However when I do a call to CreateInstance and pass in the CLSID, I get an error saying "Class not registered". Also I get this error only in some computers. It runs error free on several computers. I don't understand where the problem could be. Is my registry dirty? Does anyone know what is going on here? Thanks for your help!
I just want to add that this is a .NET COM class. The appropriate entries are in the registry and the DLL is in the GAC.
CLSIDFromProgId is simply looking up the ProgId's name in the registry and translating it to a CLSID, it doesn't have to look at anything beyond the registry or even check that something is actually implementing that CLSID.
When you call CreateInstance on the CLSID, Windows will look up in the registry to find out how the object should be instantiated (usually a exe or dll). It will then try to load the dll (or start up the exe) and create the object from it.
There is a lot of documentation in MSDN on the processes involved, for example see "COM Class Objects and CLSIDs", and if you do a lot of COM work it is worthwhile learning the process from first principals since it can save a lot of time and hassle when debugging this type of issue.
It's a two step process in the registry. You used the ProgID to get the CLSID. Then, when you call CreateInstance, COM then uses the CLSID to find the path to the dll. You can used regedit yourself to lookup the CLSID and see what that entry looks like.
Thanks for your answers. The .Net assemblies were registered properly and were present in the GAC. One application that absolutely confirmed this was Process Explorer. You can view the dlls that are loaded by each application. So from here I was able to see if the application that was instantiating the COM objects was actually able to load the DLLs or not. I found out that this was indeed happening. The problem was due to different Regional settings. We found that the application threw an exception when the region was not set to US. This issue was fixed. The error message "Class not registered" was not very helpful. Thankfully it was a quick fix.
Using shell32 as an example, you can create a new instance like so;
var shl = (Shell) Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
This will aquire a refernce to an existing component;
var shl2 = (Shell) Marshal.GetActiveObject("Shell.Application");
Here's a reference to how to do the same in IronPython.
** Note, this used the progid, clsid would be nearly identical, just use Type.GetTypeFromCLSID({GUID}).