I inherited maintainance of a complex managed/unmanaged project and I hope I can ask this question in a concise way.....
I have an unmanaged class (C++) that I am trying to access through managed code (C#). This is achieved in the following way:
The unmanaged class (Prop) is compiled into an unmanaged dll (PropUnmanaged.dll)
PropUnmanaged.dll is registered with regsvr32
regsvr32 /s PropDLL
The classes and types in PropDLL are exposed to managed code using tlbimp
This creates a managed DLL (PropTypesManaged.dll)
This dll is not registered with regasm nor gacutil
The managed class (MClass) trying to access Prop is implemented in a project that has PropTypesManaged.dll as one of its dependencies
The project that implements MClass fails with the error message
Retrieving the COM class factory for component with CLSID {1EAD9D36-495C-44B2-8559-A6570E1ECE34} failed due to the following error: 80040154
The GUID 1EAD... refers to the GUID of the exposed managed type of the Prop class generated by tlbimp. It is in the registry
Web searches on the error code vaguely suggests that something has gone wrong with the regsvr32 step, but my system reports this step succeeded OK
Where do I start debugging this?
If you're running 64-bit Windows, make sure to change the Platform Target of your C# project to x86:
Open project properties, select the Build tab, under the "General" section, select "x86" from the Platform target drop-down.
Related
I am trying to use Registration-free WinRT by adding an application manifest following https://blogs.windows.com/windowsdeveloper/2019/04/30/enhancing-non-packaged-desktop-apps-using-windows-runtime-components/ to my DLL which is used as a in-proc COM server.
However, I get REGDB_E_CLASSNOTREG when the runtime class is instantiated. I used mt.exe to make sure the manifest is embedded. I am on Win-10 2004. Is this supposed to be working for win32 in-proc DLL servers? Is there an API call to register the component manually?
It appears that the Dll activation context is not used as active activation context by the loader as found in https://stackoverflow.com/a/48308884 .
Instead we have to save the context and activate it before instantiating our runtime class as shown below:
In DllMain:
if (dwReason == DLL_PROCESS_ATTACH)
{
GetCurrentActCtx(&hActCtx);
}
And before instantiating the Runtime class:
ActivateActCtx(hActCtx, &cookie);
Class1 c;
DeactivateActCtx(0, cookie);
auto x = c.MyProperty();
By manually using the activation context API along with the embedded manifest in DLL, i can use winrt components without registration.
Make sure all dependencies related to WinRT component are present. Dependencies can be other required DLLs or VS runtime DLLs etc.
One problem I faced was: VCRUNTIME140_APP.dll not found, so I copied VC runtime libraries from the following location:
C:\program files
(x86)\msbuild\15.0.net.netnative\15.0.24211\x64\ilc\lib\MSCRT
to the output folder, post this FFmpegInteropX component got loaded into application (I think this can be solved by installing Microsoft.VCRTForwarders.140 nuget, but haven't tried it yet)
We are working on a ATL COM DLL migration project migrating code from VC++6 to VC++10 and the object_map failed to load up.
It is basically same as problem encountered by
swapnil_shinde here
The DLL shown as registered successfully, and shown in typelib, but not in the CLSID.
Existing code works fine with VC6 on Window XP but not with VC10 on Window 7.
The registration is fair standard using DLLRegisterServer of the atlbase.h in VC10.
Any idea any one?
We think the stackoverflow community is more active and variety of knowledge.
Any additional information we missed out, please ask and we will provide as well.
Thanks a lot.
Edit:
I'm running as an Administrator, 32 bit app testing on 32 bit window 7.
I have searched the entire registry for the CLSID can still cannot find it.
Try registering your object using the OBJECT_ENTRY_AUTO macro instead. In the header of each object put an reference to the entry after the class declaration, e.g.:
class CMyObject { ... class decl ... };
OBJECT_ENTRY_AUTO(__uuidof(MyObject), CMyObject)
If that doesn't work you'll need to run it through the debugger (using regsvr32 as the EXE) and watch what happens in DllRegisterServer.
Using VS11 RC. I have a client executable written in C++ that I am trying to test with a C# Unit Test Library (Metro Style apps) project. The test fails with exception Class not registered HRESULT 0x80040154 (REGDB_E_CLASSNOTRG); I believe this is related to a warning in the test project: The executable 'Client.exe' is specified as the implementation for winmd file 'C:.Client.winmd'. Only in-process servers are supported for generation of registration information in the app manifest. You will need to specify the out-of-process server registration information in the app manifest.
It appears to me that MSTest is looking for the class as a COM object, and that the warning is telling me that I need to specify it as an out-of-process server. Unfortunately, I don't think I want to do that as it is an executable, and even if that is what I want, I can't figure out how to do it.
I could simply move the class under test into a different project, but I don't want to do that without a reason better than "I can't get this to work".
Is there any way to unit test a class defined in a Metro executable?
The code to be tested needs to be moved into a DLL.
A native Windows Runtime type must be defined in a DLL in order to be activatable (this effectively means "instantiable through Windows Runtime"). Your executable doesn't need to go through Windows Runtime to instantiate types that it defines itself, but your unit test executable does need to go through Windows Runtime to instantiate those types.
I would suggest defining everything that you can in a DLL, and keeping your EXE as small as possible: have it just bootstrap your application, and put all of your real code in DLLs.
I'm running a 32 bit ver of win7 in a vm. I am trying to reference 5 com dlls (VB6) in my .net project. These dlls (and their dependencies) are registered ok since I can use them natively as they form a part of another app and that app is working fine.
I try to set a reference to any of them directly in vs and I get the error message - Library not registered (Exception from HRESULT: 0x8002801D (TYPE_E_LIBNOTREGISTERED)).
However, if I set a reference to another com component (which I don't want to reference but which in turn does reference these libs) I find that the references to these com dlls (which I do want to reference) gets set correctly in vs. I then just need to remove the ref to the unwanted dll and everything seems to be good to go.
If I look at the GUID and version details of one of the successfully referenced component, they appear to be the same as the GUID and version that appears in the caption of the error form, when I unsuccessfully try and set a reference to the same component directly.
BTW I have tried repairing the VS installation to no avail
I was wondering if someone could explain what I am doing wrong.
EDIT: Follow-up following Hans suggestion
So I ran
tlbimp mylib.dll
and it returned a TI1006 error - Output would overwrite the input file. So following suggestions found, I then issued
tlbimp mylib.dll /OUT:interop.mylib.dll
and this then returned the error
TlbImp : warning TI3011 : Type library importer has encountered an interface not derived from IUnknown: '_HiddenInterface'. The interface is skipped.
TlbImp : error TI1033 : Cannot find type 'ADODB._Recordset_Deprecated' in 'ADODB, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. There could be a mismatch between the referenced assembly and the type library.
But I'm not sure if this is a red herring since this lib could be referenced when successfully referencing the different higher level dll. I have tried with a dll which doesn't reference ADODB and that seems to work using tlbimp. So, e.g.
tlbimp myNONADODBlib.dll /OUT:interop.myNONADODBlib.dll
works from the commandline. However
tlbimp myNONADODBlib.dll
still generates the error TI1006 - output file will overwrite input file, and I cannot reference this into my .net project
EDIT:
There seems to be a problem with ADO and Win7 SP1. http://support.microsoft.com/kb/2517589 which would account for the deprecated error message (TI1033) I was getting, but not why VS was failing to create a CCW for the dll I can manually create a CCW via tlbimp.
EDIT (12/03/28 10:40):
So I have rebuilt the com dll with the suggested tlb. I can now successfully run
tlbimp mylib.dll
without getting any error messages and it appears to complete successfully. However, when I try and add a reference to that dll in VS, I still get the same original error message ( Library not registered (Exception from HRESULT: 0x8002801D (TYPE_E_LIBNOTREGISTERED))). I have checked the registry and the registration looks ok i.e. it is pointing to the correct path - I'm wondering if it is a permissions-type issue - but I am running vs as admin.
EDIT (12/03/28 10:15):
So I ended up creating a new completely new vm with the same environment - and it worked ok. So I've no idea what is going on other than some registry corruption perhaps!
Many thx
Simon.
You need to use REGTLIB.exe to register the type library of the DLLs.
Type library registration is separate from component registration - the type library supports the introspection/type explorer functionality, and isn't usually required for running a precompiled application, though it may be required for compilation.
I have a C# library that I am using for a COM object in unmanaged C++ code. I registered the library using Visual Studio's checkbox "Register For Com Interop" and set ComVisible to true.
imported the tlb to the C++ app..... when I run it, I get a "Class Not Registered"....
This has worked before, but this started happening after I moved the directory of my C# project to a different location.... yes I did re-register the library after I moved it.
I've removed all references from the registry... I 've even tried doing a gacutil.exe /i on it... no dice.
Anyone know how to fix this?
A better way of using unmanaged objects in managed code is to use C++ / CLI. You can easily create a managed wrapper around the native object.
If you don't have explicit CLSID set on your managed object, it's possible that the move and rebuild has generated a new CLSID. Make sure your unmanaged project does not have a stale copy of the typelib.
Go to HKCR\CLSID\{XXXX} and ensure that the class registration for the managed object points to the right managed dll.