无法激活 IDL 中定义的投影类型 [英] Can't activate projected type defined in IDL

查看:25
本文介绍了无法激活 IDL 中定义的投影类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 IDL 中定义 Windows 运行时类型,并使用其投影类型.从默认生成的Blank App UWP 项目(称为Blank App")开始,我添加了MyControl.idl":

命名空间 BlankApp{[默认接口]运行时类 MyControl:Windows.UI.Xaml.Controls.Control{我的控制();}}

编译解决方案,然后将MyControl.hMyControl.cppGenerated Files/sources复制到项目根目录.>

我包含了投影类型的标题并将以下代码添加到 App::OnLaunched 中:

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

这一切编译和链接都很好.在运行时,它会抛出一个 hresult_error(0x80040154:REGDB_E_CLASSNOTREG 类未注册).

引发异常时调用堆栈的顶部如下所示:

<块引用>

BlankApp.exe!winrt::hresult_error::hresult_error(const HRESULT code=REGDB_E_CLASSNOTREG 类未注册,winrt::hresult_error::from_abi_t __formal={...}) 已加载第 2977 行 C++ 符号.BlankApp.exe!winrt::throw_hresult(const HRESULT result=REGDB_E_CLASSNOTREG 类未注册) 已加载第 3211 行 C++ 符号.BlankApp.exe!winrt::check_hresult(HRESULT 结果=REGDB_E_CLASSNOTREG 类未注册)第 3261 行 C++ 符号已加载.BlankApp.exe!winrt::impl::get_activation_factory() 第 7375 行 C++ 符号已加载.BlankApp.exe!winrt::impl::factory_cache_entry<winrt::BlankApp::MyControl,winrt::Windows::Foundation::IActivationFactory>::get() 第 7448 行 C++ 符号已加载.BlankApp.exe!winrt::get_activation_factory() 第 7520 行 C++ 符号已加载.BlankApp.exe!winrt::BlankApp::MyControl::MyControl() 第 74 行 C++ 符号已加载.BlankApp.exe!winrt::BlankApp::implementation::App::OnLaunched(const winrt::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs & e={...}) 第 50 行 C++ 符号已加载.

module.g.cpp 被编译到应用程序中并包含以下代码:

HRESULT __stdcall WINRT_GetActivationFactory(HSTRING classId, void** factory){尝试{*工厂= nullptr;wchar_t const* const name = WindowsGetStringRawBuffer(classId, nullptr);if (0 == wcscmp(name, L"BlankApp.MainPage")){*factory = winrt::detach_abi(winrt::make());返回 S_OK;}if (0 == wcscmp(name, L"BlankApp.MyControl")){*factory = winrt::detach_abi(winrt::make());返回 S_OK;}#ifdef _WRL_MODULE_H_return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(classId, reinterpret_cast<::IActivationFactory**>(factory));#别的返回 winrt::hresult_class_not_available().to_abi();#万一}抓住 (...){返回 winrt::to_hresult();}}

很明显,我的类型没有被 Windows 运行时注册用于查找,即使一切似乎都在它需要的地方.有没有我遗漏的注册步骤?还是 UWP 应用程序(而不是 Windows 运行时组件)支持这一点?

解决方案

您可能需要将该类添加到 appx 清单中.

扩展元素文档中有一个示例.需要添加以下 Extension 元素:

<扩展类别="windows.activatableClass.inProcessServer"><InProcessServer><Path>BlankApp.exe</Path><ActivatableClass ActivatableClassId="BlankApp.MyControl" ThreadingModel="both"/></InProcessServer></扩展></扩展>

要允许 Windows 运行时检索激活工厂,还需要从可执行文件中导出 DllGetActivationFactory 符号.这可以通过将以下 .def 文件添加到项目中来完成:

出口DllCanUnloadNow = WINRT_CanUnloadNow 私有DllGetActivationFactory = WINRT_GetActivationFactory 私有

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?

解决方案

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

这篇关于无法激活 IDL 中定义的投影类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆