Can't activate projected type defined in IDL

浪子不回头ぞ 提交于 2019-12-12 00:52:04

问题


I was trying to define a Windows Runtime type in IDL, and consume its projected type. Going from a default-generated Blank App UWP project (called "Blank App"), I added "MyControl.idl":

namespace BlankApp
{
    [default_interface]
    runtimeclass MyControl : Windows.UI.Xaml.Controls.Control
    {
        MyControl();
    }
}

Compiled the solution, then copied MyControl.h and MyControl.cpp from Generated Files/sources to the project root directory.

I included the header for the projected type and added the following code to App::OnLaunched:

#include <winrt/BlankApp.h>

...

void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
    auto const myControl{ winrt::BlankApp::MyControl() };
    ...

This all compiled and linked fine. At runtime, it throws an hresult_error (0x80040154: REGDB_E_CLASSNOTREG Class not registered).

The top of the callstack at the point the exception is raised looks like this:

BlankApp.exe!winrt::hresult_error::hresult_error(const HRESULT code=REGDB_E_CLASSNOTREG Class not registered, winrt::hresult_error::from_abi_t __formal={...}) Line 2977  C++ Symbols loaded.
BlankApp.exe!winrt::throw_hresult(const HRESULT result=REGDB_E_CLASSNOTREG Class not registered) Line 3211  C++ Symbols loaded.
BlankApp.exe!winrt::check_hresult(HRESULT result=REGDB_E_CLASSNOTREG Class not registered) Line 3261    C++ Symbols loaded.
BlankApp.exe!winrt::impl::get_activation_factory<winrt::BlankApp::MyControl,winrt::Windows::Foundation::IActivationFactory>() Line 7375 C++ Symbols loaded.
BlankApp.exe!winrt::impl::factory_cache_entry<winrt::BlankApp::MyControl,winrt::Windows::Foundation::IActivationFactory>::get() Line 7448   C++ Symbols loaded.
BlankApp.exe!winrt::get_activation_factory<winrt::BlankApp::MyControl,winrt::Windows::Foundation::IActivationFactory>() Line 7520   C++ Symbols loaded.
BlankApp.exe!winrt::BlankApp::MyControl::MyControl() Line 74    C++ Symbols loaded.
BlankApp.exe!winrt::BlankApp::implementation::App::OnLaunched(const winrt::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs & e={...}) Line 50   C++ Symbols loaded.

module.g.cpp is compiled into the application and contains the following code:

HRESULT __stdcall WINRT_GetActivationFactory(HSTRING classId, void** factory)
{
    try
    {
        *factory = nullptr;
        wchar_t const* const name = WindowsGetStringRawBuffer(classId, nullptr);

        if (0 == wcscmp(name, L"BlankApp.MainPage"))
        {
            *factory = winrt::detach_abi(winrt::make<winrt::BlankApp::factory_implementation::MainPage>());
            return S_OK;
        }

        if (0 == wcscmp(name, L"BlankApp.MyControl"))
        {
            *factory = winrt::detach_abi(winrt::make<winrt::BlankApp::factory_implementation::MyControl>());
            return S_OK;
        }

#ifdef _WRL_MODULE_H_
        return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(classId, reinterpret_cast<::IActivationFactory**>(factory));
#else
        return winrt::hresult_class_not_available().to_abi();
#endif
    }
    catch (...)
    {
        return winrt::to_hresult();
    }
}

So apparently, my type wasn't registered for lookup by the Windows Runtime, even though everything seems to be where it needs to be. Is there some registration step I'm missing? Or is this even supported from a UWP application as opposed to a Windows Runtime Component?


回答1:


You probably need to add the class to the appx manifest.

There's an example in the Extensions element documentation. The following Extension element needs to be added:

<Extensions>
  <Extension Category="windows.activatableClass.inProcessServer">
    <InProcessServer>
      <Path>BlankApp.exe</Path>
      <ActivatableClass ActivatableClassId="BlankApp.MyControl" ThreadingModel="both" />
    </InProcessServer>
  </Extension>
</Extensions>

To allow the Windows Runtime to retrieve an activation factory, the DllGetActivationFactory symbol needs to be exported from the executable as well. This can be done by adding the following .def file to the project:

EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow                    PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory    PRIVATE


来源:https://stackoverflow.com/questions/50889858/cant-activate-projected-type-defined-in-idl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!