无法激活 IDL 中定义的投影类型
Can't activate projected type defined in IDL
我试图在 IDL 中定义一个 Windows 运行时类型,并使用它的投影类型。从 default-generated Blank App UWP 项目(称为 "Blank App")开始,我添加了 "MyControl.idl":
namespace BlankApp
{
[default_interface]
runtimeclass MyControl : Windows.UI.Xaml.Controls.Control
{
MyControl();
}
}
编译解决方案,然后从复制MyControl.h和MyControl.cpp生成Files/sources到项目根目录。
我为投影类型添加了 header 并将以下代码添加到 App::OnLaunched
:
#include <winrt/BlankApp.h>
...
void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
auto const myControl{ winrt::BlankApp::MyControl() };
...
这一切编译和链接都很好。在运行时,它抛出一个 hresult_error
(0x80040154: REGDB_E_CLASSNOTREG Class not registered).
引发异常时的调用堆栈顶部如下所示:
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 被编译到应用程序中并包含以下代码:
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();
}
}
很显然,Windows 运行时未注册我的类型以进行查找,尽管一切似乎都在需要的位置。我缺少一些注册步骤吗?或者 UWP 应用程序是否支持此功能而不是 Windows 运行时组件?
您可能需要将 class 添加到 appx 清单。
Extensions element documentation. The following Extension元素中有一个例子需要添加:
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>BlankApp.exe</Path>
<ActivatableClass ActivatableClassId="BlankApp.MyControl" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
要允许 Windows 运行时检索激活工厂,还需要从可执行文件中导出 DllGetActivationFactory
符号。这可以通过将以下 .def 文件添加到项目中来完成:
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
我试图在 IDL 中定义一个 Windows 运行时类型,并使用它的投影类型。从 default-generated Blank App UWP 项目(称为 "Blank App")开始,我添加了 "MyControl.idl":
namespace BlankApp
{
[default_interface]
runtimeclass MyControl : Windows.UI.Xaml.Controls.Control
{
MyControl();
}
}
编译解决方案,然后从复制MyControl.h和MyControl.cpp生成Files/sources到项目根目录。
我为投影类型添加了 header 并将以下代码添加到 App::OnLaunched
:
#include <winrt/BlankApp.h>
...
void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
auto const myControl{ winrt::BlankApp::MyControl() };
...
这一切编译和链接都很好。在运行时,它抛出一个 hresult_error
(0x80040154: REGDB_E_CLASSNOTREG Class not registered).
引发异常时的调用堆栈顶部如下所示:
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 被编译到应用程序中并包含以下代码:
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();
}
}
很显然,Windows 运行时未注册我的类型以进行查找,尽管一切似乎都在需要的位置。我缺少一些注册步骤吗?或者 UWP 应用程序是否支持此功能而不是 Windows 运行时组件?
您可能需要将 class 添加到 appx 清单。
Extensions element documentation. The following Extension元素中有一个例子需要添加:
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>BlankApp.exe</Path>
<ActivatableClass ActivatableClassId="BlankApp.MyControl" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
要允许 Windows 运行时检索激活工厂,还需要从可执行文件中导出 DllGetActivationFactory
符号。这可以通过将以下 .def 文件添加到项目中来完成:
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE