如何:使用 WRL 激活和使用 Windows 运行时组件

本文档演示如何使用 Windows 运行时 C++ 模板库 (WRL) 初始化 Windows 运行时,以及如何激活和使用 Windows 运行时组件。

若要使用组件,必须获取指向组件实现的类型的接口指针。 由于 Windows 运行时的基础技术是组件对象模型 (COM),因此必须遵循 COM 规则来维护此类型的实例。 例如,必须维护引用计数,其可以确定何时从内存中删除此类型。

为了简化 Windows 运行时的使用,Windows 运行时 C++ 模板库提供了可以自动执行引用计数的智能指针模板 ComPtr<T>。 声明变量时,请指定 ComPtr<接口名称> 标识符。 若要访问接口成员,请将箭头成员访问运算符 (->) 应用于标识符。

重要

调用接口函数时,请务必测试 HRESULT 返回值。

激活和使用 Windows 运行时组件

以下步骤使用 Windows::Foundation::IUriRuntimeClass 接口演示如何为 Windows 运行时组件创建激活工厂、创建该组件的实例以及检索属性值。 它们还演示如何初始化 Windows 运行时。 之后提供了完整示例。

重要

尽管通常在通用 Windows 平台 (UWP) 应用中使用 Windows 运行时 C++ 模板库,但此示例使用控制台应用进行演示。 UWP 应用不提供 wprintf_s 等函数。 若要详细了解可在 UWP 应用中使用的类型和函数,请参阅通用 Windows 平台应用中不支持的 CRT 函数适用于 UWP 应用的 Win32 和 COM

激活和使用 Windows 运行时组件

  1. 包括 (#include) 任何所需的 Windows 运行时、Windows 运行时 C++ 模板库或 C++ 标准库标头。

    #include <Windows.Foundation.h>
    #include <wrl\wrappers\corewrappers.h>
    #include <wrl\client.h>
    #include <stdio.h>
    
    using namespace ABI::Windows::Foundation;
    using namespace Microsoft::WRL;
    using namespace Microsoft::WRL::Wrappers;
    

    我们建议您在 .cpp 文件中使用 using namespace 指令使代码更具可读性。

  2. 初始化应用执行所在的线程。 每个应用都必须初始化其线程和线程模型。 此示例使用 Microsoft::WRL::Wrappers::RoInitializeWrapper 类初始化 Windows 运行时,并将 RO_INIT_MULTITHREADED 指定为线程模型。 RoInitializeWrapper 类在构造时调用 Windows::Foundation::Initialize,销毁时调用 Windows::Foundation::Uninitialize

    // Initialize the Windows Runtime.
    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
    if (FAILED(initialize))
    {
        return PrintError(__LINE__, initialize);
    }
    

    在第二个语句中,RoInitializeWrapper::HRESULT 运算符从 Windows::Foundation::Initialize 调用返回 HRESULT

  3. ABI::Windows::Foundation::IUriRuntimeClassFactory 接口创建激活工厂。

    // Get the activation factory for the IUriRuntimeClass interface.
    ComPtr<IUriRuntimeClassFactory> uriFactory;
    HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }
    

    Windows 运行时使用完全限定名来标识类型。 RuntimeClass_Windows_Foundation_Uri 参数是 Windows 运行时提供的字符串,其中包含所需的运行时类名称。

  4. 初始化 Microsoft::WRL::Wrappers::HString 变量,其用于表示 URI "https://www.microsoft.com"

    // Create a string that represents a URI.
    HString uriHString;
    hr = uriHString.Set(L"http://www.microsoft.com");
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }
    

    在 Windows 运行时中,不要为 Windows 运行时将使用的字符串分配内存。 相反,Windows 运行时会在它维护和用于操作的缓冲区中创建字符串的副本,然后将句柄返回到其创建的缓冲区。

  5. 使用 IUriRuntimeClassFactory::CreateUri 工厂方法创建 ABI::Windows::Foundation::IUriRuntimeClass 对象。

    // Create the IUriRuntimeClass object.
    ComPtr<IUriRuntimeClass> uri;
    hr = uriFactory->CreateUri(uriHString.Get(), &uri);
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }
    
  6. 调用 IUriRuntimeClass::get_Domain 方法以检索 Domain 属性的值。

    // Get the domain part of the URI.
    HString domainName;
    hr = uri->get_Domain(domainName.GetAddressOf());
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }
    
  7. 将域名输出到控制台并返回。 所有 ComPtr 和 RAII 对象都离开范围并自动释放。

    // Print the domain name and return.
    wprintf_s(L"Domain name: %s\n", domainName.GetRawBuffer(nullptr));
    
    // All smart pointers and RAII objects go out of scope here.
    

    WindowsGetStringRawBuffer 函数可检索 URI 字符串的基础 Unicode 格式。

以下是完整示例:

// wrl-consume-component.cpp
// compile with: runtimeobject.lib
#include <Windows.Foundation.h>
#include <wrl\wrappers\corewrappers.h>
#include <wrl\client.h>
#include <stdio.h>

using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

// Prints an error string for the provided source code line and HRESULT
// value and returns the HRESULT value as an int.
int PrintError(unsigned int line, HRESULT hr)
{
    wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr);
    return hr;
}

int wmain()
{
    // Initialize the Windows Runtime.
    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
    if (FAILED(initialize))
    {
        return PrintError(__LINE__, initialize);
    }

    // Get the activation factory for the IUriRuntimeClass interface.
    ComPtr<IUriRuntimeClassFactory> uriFactory;
    HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }

    // Create a string that represents a URI.
    HString uriHString;
    hr = uriHString.Set(L"http://www.microsoft.com");
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }

    // Create the IUriRuntimeClass object.
    ComPtr<IUriRuntimeClass> uri;
    hr = uriFactory->CreateUri(uriHString.Get(), &uri);
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }

    // Get the domain part of the URI.
    HString domainName;
    hr = uri->get_Domain(domainName.GetAddressOf());
    if (FAILED(hr))
    {
        return PrintError(__LINE__, hr);
    }

    // Print the domain name and return.
    wprintf_s(L"Domain name: %s\n", domainName.GetRawBuffer(nullptr));

    // All smart pointers and RAII objects go out of scope here.
}
/*
Output:
Domain name: microsoft.com
*/

编译代码

若要编译代码,请复制代码并将其粘贴到 Visual Studio 项目中,或粘贴到一个名为 wrl-consume-component.cpp 的文件中,然后在 Visual Studio 命令提示符窗口中运行以下命令。

cl.exe wrl-consume-component.cpp runtimeobject.lib

另请参阅

Windows 运行时 C++ 模板库 (WRL)