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)
Related
I have a MFC project using the shared MFC DLL (MFC140UD.DLL).
I want to set the trace level in my debug version to level 4, to get more information about message pumping.
But using CTrace::SetLevel in my code, just sets the debug level for the CTrace object in my personal modules (my EXE file). CTrace ist declared as __declspec(selectany). In the exported symbols of the MFC140UD.LIB I can see no export for the class CTrace or its members.
So using CTrace::SetLevel has no effect on the MFC core MFC140UD.DLL. I always have to set a breakpoint inside the atltrace.h and need to modify the static m_nLevel value in the debugger.
Is there any trick to access the CTrace::m_nLevel value inside the MFC core DLL from my outer MFC EXE?
Note: Also the old AtlTraceTool stuff isn't no longer working and supported.
It should be impossible to access the CTrace::m_nLevel value inside the MFC core DLL from your outer MFC EXE. Each module has its own instance of the CTrace class, that is, you should get the static member variable CTrace::m_nLevel set to the appropiate value in the context of each module. So I'm afraid you cannot configure the trace level in MFC140UD.DLL from your own module when you using the shared MFC DLL.
You can try to call API AtlTraceModifyModule to Set trace level of MFC140UD.dll.
I'm currently trying to get a rather tangled scheme running with registration free COM.
It's not that it is not working, it's that I have hit a kind of confusing situation, where it seems I should active the manifest of the assembly dependency directly in the application context, rather than have the application context point at the dependent assembly.
It is rather easy to explain by the example project MS themselves publish:
Normally, you have an application, an app manifest, a (server-)dll and it's assembly manifest. These correspond to what the example gives:
client.exe
client.exe.manifest (This one points to SideBySide.X as dependentAssembly)
SideBySide.dll
SideBySide.X.manifest
Now, one standard case is to embed the client application manifest inside the client executable, and then use the DLL and its external manifest file.
Now, if for whatever reason the correct application manifest isn't known at compile time, you can load a manifest file at runtime via the Activation Context API.
And this is where it gets confusing:
According to the article, the client application now directly switches its Activation Context to the assembly manifest:
If you look at the _tmain function in client.cpp ... a new section of code that initializes the activation context as follows:
actCtx.lpSource = "SideBySide.X.manifest";
I have cross checked this, and it would also work to dynamically load a file that contains the info from client.exe.manifest, i.e. just the reference to SideBySide.X, and continue with this Activation Context - which would also correspond to the ActCtx in use when we embed a correct application manifest into the executable.
That is, actCtx.lpSource = "client.exe.manifest"; would also work.
TL;DR What is the implication, if any, of directly activating an Activation Context "containing" an assembly manifest inside application code.
Is this how it's supposed to be done when loading manifests from files? (And if so, why can't we directly embed the assembly manifest into the executable, when it is known at compile time.)
Note: (This should really be a comment to #Eric Brown's answer, but it's getting rather lengthy)
The linked article does a decent job of explaining the two RT_MANIFESTresource types, but with regard to regFreeCOm, it leaves a few loose ends. I'll throw in some quotes that jumped at me:
ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It
should be used if the dll wants private dependencies other than the
process default. ...
the NT library loader checks to see if the
dll has a resource of type RT_MANIFEST, ID
ISOLATIONAWARE_MANIFEST_RESOURCE_ID. If it does, the loader calls
CreateActCtx with the resource, and use the generated activation
context to probe the dll's static dependencies.
What I understand this to mean is that the only point of RT_MANIFEST/2 is for the static DLL dependency loader to find the correct resource to use for resolving DLL dependencies. (Not COM dependencies, see below.)
Sometimes, you want to use the activation context outside of probing
the dll's static dependencies. You can define macro
ISOLATION_AWARE_ENABLED when you compile the module.
When ISOLATION_AWARE_ENABLED is defined, Windows re-defines certain
APIs. For example LoadLibraryExW is redefined to
IsolationAwareLoadLibraryExW.
... Not all APIs affected by activation context are wrapped. For example,
..., and neither is any of the COM APIs.
So, to sum up: I think the RT_MANIFEST mechanism is mostly orthogonal to regFreeCOM as COM doesn't care at all where it's activation context comes from and there is no built-in help for regFreeCOM wrt. Isolation Awareness.
Yes, this is how it's supposed to be done, and you can embed the assembly manifest into the executable (well, the resource section). That's what the RT_MANIFEST resource type is for. There are two default types of manifest resources
Process manifests, with ID CREATEPROCESS_MANIFEST_RESOURCE_ID (1), used during process creation,
Isolation-Aware manifests, with ID ISOLATIONAWARE_MANIFEST_RESOURCE_ID (2), used during DLL loading.
There are a couple of uses (primarily around Click-once deployment) that illustrate the ability to embed registration-free COM manifests in subsidiary DLLs, using RT_MANIFEST. In particular, if a DLL has a CREATEPROCESS_MANIFEST_RESOURCE_ID, that manifest will be used as well.
An example seems like a good thing here.
Given
client.exe
sidebyside.dll
If sidebyside.dll has an RT_MANIFEST resource with ID 1 (CREATEPROCESS_MANIFEST_RESOURCE_ID) which has the appropriate registration-free COM entries in it, and client.exe has an RT_MANIFEST resource with ID 1 that has a <file> entry for sidebyside.dll, then Win32 will automatically handle the registration-free COM management.
Part 8 of the example article strongly implies this, and I've seen it done in a number of in-house projects.
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 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.