Windows Runtime helpers - microsoft/wil GitHub Wiki (2025)

In the wil/winrt.h and wil/wrl.h header files,WIL provides helpers to facilitate consumption of Windows Runtime APIsat the ABI (unprojected) layer:

#include <wil/winrt.h>#include <wil/wrl.h>

These helpers work well together with the smart pointers and other WinRT and COM wrappers inwil/com.h.

Note: These helpers have been superseded by theC++/WinRT projection.You should prefer C++/WinRT in new code, perhaps along withWIL's integration with C++/WinRT.

The time helpers require that <time.h> be included before including wil/winrt.h.

SecondsToStartOf1970

long long const SecondsToStartOf1970 = 0x2b6109100;

The number of seconds from the Windows Runtime epoch to January 1, 1970. The Windows Runtime epoch is January 1, 1601.

HundredNanoSecondsInSecond

long long const HundredNanoSecondsInSecond = 10000000LL;

The number of Windows Runtime time units per second. One Windows Runtime time unit is 100ns.

DateTime_to_time_t

__time64_t DateTime_to_time_t(DateTime dateTime);

Converts a Windows Runtime DateTime to a 64-bit C runtime (Unix-style) time value. The 64-bit C runtime time format has a larger range than the Windows Runtime DateTime format, but cannot represent fractional seconds. Fractional seconds are discarded in the conversion.

The C++/WinRT equivalent iswinrt::clock::to_time_t().

time_t_to_DateTime

DateTime time_t_to_DateTime(__time64_t timeT);

Converts a 64-bit C runtime (Unix-style) time value to a Windows Runtime DateTime.

The result is undefined if the 64-bit C runtime time value represents a point in time that cannot be represented by a DateTime (approximate range 27,400 B.C.E to 29,000 C.E.).

The C++/WinRT equivalent iswinrt::clock::from_time_t().

HasEmbeddedNull

bool HasEmbeddedNull(_In_opt_ HSTRING value);

Returns true if the string contains an embedded null character.

The C++/WinRT equivalent is winrt::embedded_null(hstring const&).

TwoPhaseHStringConstructor

The TwoPhaseHStringConstructor is a helper class for constructing HSTRING objects. It is movable but not copyable.

The C++/WinRT equivalent is to construct the stringusing std::wstring or any other convenient string container,then construct an hstring from it.

Usage

// Preallocate space for a string of a specific length.// The length does not include the null terminator.auto stringConstructor = wil::TwoPhaseHStringConstructor::Preallocate(length);RETURN_IF_NULL_ALLOC(stringConstructor.Get());// Fill the buffer with exactly length characters.RETURN_IF_FAILED(stream->Read(stringConstructor.Get(), stringConstructor.ByteSize(), &bytesRead));// Validate stream contents: Sizes must match, and// preallocated null terminator must still be present.RETURN_IF_FAILED(stringConstructor.Validate(bytesRead));Microsoft::WRL::Wrappers::HString string;string.Attach(stringConstructor.Promote());

Details

Constructors

  • static TwoPhaseHStringConstructor TwoPhaseHStringConstructor::Preallocate(UINT32 characterLength) (factory)
    Create a new TwoPhaseHStringConstructor that will eventually holda string of characterLength characters (not counting the null terminator).

  • TwoPhaseHStringConstructor(TwoPhaseHStringConstructor&& other) (move constructor)
    Transfer the state of a TwoPhaseHStringConstructor to a new object.

Destructor

  • ~TwoPhaseHStringConstructor
    It is acceptable to destruct the object without calling Promote.In that case, the construction of the HSTRING is abandoned.

Methods

  • wchar_t* Get()
    Returns a pointer to the buffer into which the string should be generated.

  • ULONG ByteSize() const
    Returns the size of the buffer in bytes.

  • HRESULT Validate(ULONG bytesRead) const
    Validates that the number of bytes is equal to the size of the buffer,not including the null terminator.Also validates that the buffer's null terminator has not been corrupted.

    Calling Validate() is optional.

  • HSTRING Promote()
    Construct the Windows Runtime HSTRING object from the informationin the buffer. The caller is responsible for the lifetime of the resultingHSTRING. It is typically placed into an RAII type such as wil::unique_hstring.Once the string is promoted, the only thing you can do with the objectis destruct it.

    The Promote() method fails fast on usage error,such as if the null terminator has been corrupted,or if you attempt to Promote() twice.

Operators

  • operator PCWSTR() const
    Returns the buffer into which the string was generated.

hstring_less and hstring_insensitive_less

The hstring_less and hstring_insensitive_less structures performcase-sensitive or case-insensitive (respectively) ordinal string comparisonson HSTRING objects.

They aretransparentcomparatorswhich permit more efficient use of HSTRINGs as keys in associativecontainers such as std::set and std::map.Transparency permits looking up items usingany of the following:

  • HSTRING
  • const Microsoft::WRL::Wrappers::HString&
  • const Microsoft::WRL::Wrappers::HStringReference&
  • const wil::unique_hstring&
  • const wchar_t* (null-terminated string, null pointer treated as empty string)
  • const std::string& (if exceptions are enabled)

Note that the const wchar_t* version cannot be used to search forstrings with embedded nulls, because the embedded null will betreated as a string terminator.

The hstring_less structure is used as the default std::lesscomparator for Microsoft::WRL::HString andwil::unique_hstring.

Examples:

std::map<Microsoft::WRL::HString, int, wil::hstring_less> map;Microsoft::WRL::HString str = ...;wil::unique_hstring uniqueStr = ...;wchar_t buffer[...];map.find(str); // Traditional lookup via Microsoft::WRL::HStringmap.find(str.Get()); // Transparent lookup accepts HSTRINGmap.find(uniqueStr); // Transparent lookup accepts wil::unique_hstringmap.find(L"literal"); // Transparent lookup accepts const wchar_t*map.find(buffer); // Transparent lookup accepts wchar_t*map.find(std::wstring(buffer)); // Transparent lookup accepts std::wstring

The get_range adapters permit use ofrange-based for loopsto iterate over Windows Runtime collections.

AdapterError model
get_rangeExceptions
get_range_nothrowError codes
get_range_failfastFail fast

C++/WinRT does not require an adapter.Range-based for loops are natively supported over C++/WinRT collections(anything that supports Windows.Foundation.IIterable<T>).

See Ad-hoc range helpers for other iterator helpers.

Examples

// assume collection is IVector<T>*, IVectorView<T>*, or IIterable<T>*for (auto const& element : wil::get_range(collection)) ...for (auto const& element : wil::get_range_failfast(collection)) ...for (auto const& element : wil::get_range_nothrow(collection)) ...for (auto const& element : wil::get_range_nothrow(collection, &hr)) ...

In the case of get_range_nothrow, an optional HRESULT* parameterreceives the HRESULT that caused the iteration to stop.If the iterator ran to completion successfully,or if the loop was explicitly exited with a break statement,then the value will be S_OK.

Warnings

  • It is the caller's responsibility to ensure that thecollection lifetime extends to the completion of the for loop.
  • The collection's lifetime must encompass theuse of the iterators you obtain from the get_range functions.
  • The iterators obtained from get_range and get_range_failfastarebidirectional iteratorswhich also support constant-time bidirectional advance.
  • The iterators obtained from get_range_nothrow functionareinput iteratorswhich also support constant-time bidirectional advance.However, only one iterator may be dereferenced.
extern Microsoft::WRL::ComPtr<IVector<T>> GetCollection();// WRONG! The smart pointer returned by GetCollection() is temporary// and will be destructed before the loop body runs.for (auto const& element : wil::get_range(GetCollection().Get())) ...// FIXED! Explicitly extend the lifetime of the collection.auto collection = GetCollection();for (auto const& element : wil::get_range(collection.Get())) ...// WRONG! The smart pointer returned by GetCollections() is temporary// and will be destructed while there are still active iterators.auto range = wil::get_range(GetCollection().Get());auto it = std::lower_bound(range.begin(), range.end(), value);// FIXED! Explicitly extend the lifetime of the collection.auto collection = GetCollection();auto range = wil::get_range(collection.Get());auto it = std::lower_bound(range.begin(), range.end(), value);// WRONG! The iterators produced by get_range_nothrow// are not forward iterators.auto collection = GetCollection();auto range = wil::get_range_nothrow(collection.Get());auto it = std::adjacent_find(range.begin(), range.end());

These functions permit basic operations with Windows Runtimeasynchronous operations,but they have been superseded byC++/WinRT.

For all the asynchronous operation helpers,the operation can be

  • An "action", which has no result: IAsyncAction* or IAsyncActionWithProgress<TProgress>*
  • An "operation": IAsyncOperation<TResult>* or IAsyncOperationWithProgress<TResult, TProgress>*

Running code when an asynchronous operation completes

These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT and co_await to consume asynchronous operations.

FunctionError model
run_when_completeExceptions
run_when_complete_nothrowError codes
(no fail fast version)

The general shape of the run_when_complete family of functions is

template<typename TAgility>run_when_complete(operation, functor)

The TAgility can be explicitly specified as Microsoft::WRL::FtmBaseto specify that the functor can be called on any thread.By default, the functor will be called back in the same apartment.

The functor's operator() can take one of the following forms:

  • For an action:
    • HRESULT func(HRESULT hr);
    • void func(HRESULT hr);
  • For an operation whose result is an interface type
    • HRESULT func(HRESULT hr, TResult* result);
    • void func(HRESULT hr, TResult* result);
  • For an operation whose result is a value type
    • HRESULT func(HRESULT hr, TResult result);
    • void func(HRESULT hr, TResult result);

The hr reports whether the asynchronous operation completed successfully.

The result is the result of the asynchronous operation.If the asynchronous operation failed, then result is meaningless.

If the functor returns an HRESULT, then that HRESULT is the return valueof the continuation.

If the functor returns void, then exceptions thrown by THROW_IF_FAILEDare caught and treated as the return value of the continuation.

The run_when_complete function throws an exception if the continuationcannot be scheduled.

The run_when_complete_nothrow function returns an HRESULT specifyingwhether the continuation was successfully scheduled.

template<typename TAgility = IUnknown, typename TFunc>void run_when_complete(IAsyncAction* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TProgress, typename TFunc>void run_when_complete(IAsyncActionWithProgress<TProgress>* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TResult, typename TFunc>void run_when_complete(IAsyncOperation<TResult>* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc>void run_when_complete(IAsyncOperationWithProgress<TResult, TProgress>* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncAction* operation, TFunc&& func) noexcept;template<typename TAgility = IUnknown, typename TProgress, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncActionWithProgress<TProgress>* operation, TFunc&& func) noexcept;template<typename TAgility = IUnknown, typename TResult, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncOperation<TResult>* operation, TFunc&& func) noexcept;template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncOperationWithProgress<TResult, TProgress>* operation, TFunc&& func) noexcept;

Examples:

void CopyToParentFolderFireAndForget(IStorageFile* file){ Microsoft::WRL::ComPtr<IAsyncOperation<StorageFolder>> fileOperation; THROW_iF_FAILED(file->GetParentAsync(&fileOperation)); // Must extend lifetime of "file" into the lambda. run_when_complete(fileOperation.Get(), [file = wil::com_ptr<IStorageFile>(file)](HRESULT result, IStorageFolder* folder) { THROW_IF_FAILED(result); Microsoft::WRL::ComPtr<IAsyncOperation<StorageFolder>> copyOperation; THROW_IF_FAILED(file->CopyAsync(folder, &copyOperation)); run_when_complete(copyOperation.Get(), [](HRESULT result, IStorageFile* /* copiedFile */) { THROW_IF_FAILED(result); }); });}// To permit the continuation to run in any thread, use FtmBase.run_when_complete<FtmBase>(fileOperation.Get(), [](HRESULT result, IStorageFile* file){ THROW_IF_FAILED(result); DoSomethingWith(file);});

Note that the lambda must extend the lifetimes of any objects it needs,because its execution is deferred until the completion of the asynchronous operation.In particular, it must not capture by reference.

Preferred C++/WinRT alternative:

// "file" parameter is non-const because we use it in the continuation.winrt::fire_and_forget CopyToParentFolder(StorageFile file){ auto folder = co_await file.GetParentAsync(); co_await file.CopyAsync(folder);}

Waiting for an asynchronous operation to complete

These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT and get() to consume asynchronous operations synchronously.

FunctionError model
wait_for_completionExceptions
wait_for_completion_nothrowError codes
(no fail fast version)
wait_for_completion_or_timeout_nothrowError codes
call_and_wait_for_completionExceptions

These functions wait for an asynchronous operation to complete or be canceled.Use them to wait synchronously from background threads.Do not use them from UI threads or STA threads as reentrancy will result.

The general shape of the wait_for_completion family of functions is

HRESULT hr = wait_for_completion_nothrow(operation, &result);auto result = wait_for_completion(operation);

If the operation is an action, then wait_for_completion_nothrowhas no result parameter, and wait_for_completion returns void.

An optional final parameter of type COWAIT_FLAGScan be provided to customize how the thread waitsfor the operation to complete.The default is COWAIT_DISPATCH_CALLS.

If the function is unable to wait for the operation,or if the operation does not complete successfully,the error code is thrown (wait_for_completion)or returned (wait_for_completion_nothrow).No value is placed into result.

void wait_for_completion(IAsyncAction* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);void wait_for_completion(IAsyncActionWithProgress<TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);details::MapToSmartType<TResult> wait_for_completion(IAsyncOperation<TResult>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);details::MapToSmartType<TResult> wait_for_completion(IAsyncOperationWithProgress<TResult, TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);HRESULT wait_for_completion_nothrow( IAsyncAction* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_nothrow( IAsyncActionWithProgress<TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_nothrow( IAsyncOperation<TResult>* operation, details::MapAsyncOpResultType<TResult>::type* result, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_nothrow( IAsyncOperationWithProgress<TResult, TProgress>* operation, details::MapAsyncOpResultType<TResult>::type* result, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;

details::MapToSmartType<TResult> depends on the nature of TResult:

  • If TResult is HSTRING, then details::MapToSmartType<TResult>is Microsoft::WRL::Wrappers::HString, with an additional methodReleaseAndGetAddressOf.
  • If TResult is an interface type, then details::MapToSmartType<TResult> isMicrosoft::WRL::ComPtr<TResult>.
  • If TResult is a value type, then details::MapToSmartType<TResult> isa custom type which behaves similarly to Microsoft::WRL::ComPtr.
    • operator TResult() const (conversion operator)
      returns the wrapped value.
    • TResult Get() const
      returns the wrapped value.
    • TResult&& Get()
      returns the wrapped value as an rvalue reference.
    • HRESULT CopyTo(TResult* result) const
      copies the wrapped value, always returns S_OK.
    • TResult* GetAddressOf()
      returns the address of the wrapped value.
    • TResult* ReleaseAndGetAddressOf()
      returns the address of the wrapped value.
    • TResult* operator&()
      returns the address of the wrapped value.

details::MapAsyncOpResultType<TResult>::type also depends on the nature of TResult:

  • If TResult is an interface type, thendetails::MapAsyncOpResultType<TResult>::type isTResult*.
  • Otherwise,details::MapAsyncOpResultType<TResult>::type isTResult.

Waiting for completion with a timeout is done with thewait_for_completion_or_timeout_nothrow function:

HRESULT hr = wait_for_completion_or_timeout_nothrow(operation, &result, timeout, &timedOut);

Again the result is omitted if the operation is an action.

The timeout is expressed in milliseconds.If the operation fails to complete before the timeout elapses,the wait_for_completion_or_timeout_nothrow functionreturns S_OK and sets timedOut to true.In all other cases, timedOut is false.

Aside from the timeout,the function behaves the same as wait_for_completion_nothrow.

HRESULT wait_for_completion_or_timeout_nothrow( IAsyncAction* operation, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_or_timeout_nothrow( IAsyncActionWithProgress<TProgress>* operation, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_or_timeout_nothrow( IAsyncOperation<TResult>* operation, details::MapAsyncOpResultType<TResult>::type* result, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_or_timeout_nothrow( IAsyncOperationWithProgress<TResult, TProgress>* operation, details::MapAsyncOpResultType<TResult>::type* result, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;

The call_and_wait_for_completion variantuses the following pattern:

auto result = call_and_wait_for_completion(object, &Object::Method, args...);

It invokes the method on the object with the args...,and then performs a wait_for_completion on the operation.

template<typename I, typename ...P, typename ...Args>auto call_and_wait_for_completion(I* object, HRESULT(STDMETHODCALLTYPE I::*func)(P...), Args&&... args);

Examples:

IAsyncAction* action = ...;IAsyncOperation<int> intOperation = ...;IAsyncOperation<IInspectable> inspectableOperation = ...;// Waits for the action to complete, or throws if the action fails.wait_for_completion(action);// Waits for the operation to complete and returns the result.auto intResult = wait_for_completion(intOperation).Get();auto result = wait_for_completion(inspectableOperation);IInspectable* inspectable = result.Get(); // lifetime controlled by "result"// Call an asynchronous method and wait for the result.Microsoft::WRL::ComPtr<ILauncherStatics> launcherStatics = ...;auto result = call_and_wait_for_completion( launcherStatics.Get(), &ILauncherStatics::LaunchUriAsync, uri.Get());bool succeeded = result.Get();

Preferred C++/WinRT alternative:

IAsyncAction action = ...;IAsyncOperation<int32_t> intOperation = ...;IAsyncOperation<IInspectable> inspectableOperation = ...;// Waits for the action to complete, or throws if the action fails.action.get();// Waits for the operation to complete and returns the result.auto intResult = intOperation.get();IInspectable inspectable = inspectableOperation.get();// Call an asynchronous method and wait for the result.bool succeeded = winrt::Windows::System::Launcher::LaunchUriAsync(uri).get();

Creating already-completed asynchronous operations

These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT and co_return to produce asynchronous operations.

The make_synchronous_async_... functionscreate asynchronous operations which have already completedwith a particular result.They are primarily intended for testing and mocking purposes.

FunctionError model
make_synchronous_async_actionExceptions
make_synchronous_async_operationExceptions
make_synchronous_async_action_nothrowError codes
make_synchronous_async_operation_nothrowError codes
(no fail fast version)
void make_synchronous_async_action(IAsyncAction** result);void make_synchronous_async_operation(IAsyncOperation<TResult>** result, const TResult& value);HRESULT make_synchronous_async_action_nothrow(IAsyncAction** result);HRESULT make_synchronous_async_operation_nothrow(IAsyncOperation<TResult>** result, const TResult& value);

The make_synchronous_async_action andmake_synchronous_async_action_nothrow functions createan already-completed IAsyncAction.

The make_synchronous_async_operation andmake_synchronous_async_operation_nothrow functions createan already-completed IAsyncOperation<TResult>,with the specified value as the completion result.

These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT to access static methodsand construct objects.

GetActivationFactory

template<typename TInterface>com_ptr<TInterface> GetActivationFactory(PCWSTR runtimeClass);

The GetActivationFactory function gets the activation factoryfor the named Windows Runtime class.

The TInterface is the desired factory interface,usually a ISomethingStatics interface.

If the factory could not be obtained,or the factory does not support the specified interface,then an exception is thrown.

Example:

// Invoking a static method.using namespace ABI::Windows::Security::Cryptography;auto statics = wil::GetActivationFactory<ICryptographicBufferStatics>( RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer);uint32_t number;THROW_IF_FAILED(statics->GenerateRandomNumber(&number));// Constructing with parameters.using namespace ABI::Windows::Security::Credentials;auto factory = wil::GetActivationFactory<IPasswordCredentialFactory>( RuntimeClass_Windows_Security_Credentials_PasswordCredential);wil::unique_hstring resource = ...;wil::unique_hstring userName = ...;wil::unique_hstring password = ...;wil::com_ptr<IPasswordCredential> credential;THROW_IF_FAILED(factory->CreatePasswordCredential( resource.get(), userName.get(), password.get(), &credential));

Preferred C++/WinRT alternative:

// Invoking a static method.using namespace winrt::Windows::Security::Cryptography;uint32_t number = CryptographicBuffer::GenerateRandomNumber();// Constructing with parameters.using namespace winrt::Windows::Security::Credentials;winrt::hstring resource = ...;winrt::hstring userName = ...;winrt::hstring password = ...;PasswordCredential credential{ resource, userName, password };

ActivateInstance

template <typename TInterface>com_ptr<TInterface> ActivateInstance(PCWSTR runtimeClass);

The ActivateInstance function activates an instanceof the named Windows Runtime classwith no parameters.In projected languages, this is equivalent toinvoking the default constructor.

The TInterface is the desired interface on theresulting object.It is usually the object's default interface.

If the object could not be activated,or the object does not support the specified interface,then an exception is thrown.

Example:

using namespace ABI::Windows::Security::Credentials;wil::com_ptr<IPasswordCredential> credential = wil::ActivationInstance<IPasswordCredential>();

Preferred C++/WinRT alternative:

using namespace winrt::Windows::Security::Credentials;PasswordCredential credential;

These macros have been superseded byC++/WinRT.Prefer to use C++/WinRT to consume Windows Runtime events.

The unique_winrt_event_token RAII typesmanage the EventRegistrationToken for Windows Runtime eventsand unregister the event handler at destruction.

These types are often used in member variables.

The unique_winrt_event_token types maintain a weak reference to theevent source.The WI_MakeUniqueWinrtEventToken macros will fail if the event sourcedoes not support weak references.

  • WI_MakeUniqueWinRtEventToken(EventName, eventSource, handler, &token)
    Registers for the eventSource::EventName event with the specified handler.The token is stored in a unique_winrt_event_token<Source>.Throws an exception on failure.

  • WI_MakeUniqueWinRtEventTokenFailFast(EventName, eventSource, handler, &token)
    Registers for the eventSource::EventName event with the specified handler.The token is stored in a unique_winrt_event_token<Source>.Fails fast on failure.

  • WI_MakeUniqueWinRtEventTokenNoThrow(EventName, eventSource, handler, &token)
    Registers for the eventSource::EventName event with the specified handler.The token is stored in a unique_winrt_event_token<Source>.Returns an HRESULT to indicate whether the operation succeeded.

  • WI_MakeUniqueWinRtEventTokenCx(EventName, eventSource, handler)
    Registers for the eventSource::EventName event with the specified handler.The token is returned as a unique_winrt_event_token_cx<Source>.Throws an exception on failure.

  • WI_MakeUniqueWinRtStaticEventTokenCx(EventName, Source, handler)
    Registers for the static Source::EventName event with the specified handler.The token is returned as a unique_winrt_event_token_cx<Source>.Throws an exception on failure.

Note that only WI_MakeUniqueWinRtStaticEventTokenCx supports static events.

Usage

Example of ABI usage:

wil::com_ptr<Widget> widget = ...;wil::com_ptr<TypedEventHandler<Widget, WidgetClosedEventArgs>> handler = ...;wil::unique_winrt_event_token<Widget> token;// Using exceptions.WI_MakeUniqueWinRtEventToken(Closed, widget.get(), handler.get(), &token);// Using fail-fast.WI_MakeUniqueWinRtEventTokenFailFast(Closed, widget.get(), handler.get(), &token);// Using HRESULTs.RETURN_IF_FAILED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, widget.get(), handler.get(), &token));

Example of C++/CX usage:

Widget^ widget = ...;TypedEventHandler<Widget, WidgetClosedEventArgs>^ handler = ...;// Register an instance event, throws on failure.wil::unique_winrt_event_token_cx<Widget> token = WI_MakeUniqueWinRtEventTokenCx(Closed, widget, handler);// Register a static event, throws on failure.EventHandler<WidgetAddedEventArgs>^ handler = ...;wil::unique_winrt_event_token_cx<Widget> token = WI_MakeUniqueWinRtStaticEventTokenCx(WidgetAdded, Widget, handler);

The C++/WinRT equivalent is winrt::event_revoker.

Windows Runtime helpers - microsoft/wil GitHub Wiki (2025)

References

Top Articles
Latest Posts
Recommended Articles
Article information

Author: Tuan Roob DDS

Last Updated:

Views: 5894

Rating: 4.1 / 5 (62 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Tuan Roob DDS

Birthday: 1999-11-20

Address: Suite 592 642 Pfannerstill Island, South Keila, LA 74970-3076

Phone: +9617721773649

Job: Marketing Producer

Hobby: Skydiving, Flag Football, Knitting, Running, Lego building, Hunting, Juggling

Introduction: My name is Tuan Roob DDS, I am a friendly, good, energetic, faithful, fantastic, gentle, enchanting person who loves writing and wants to share my knowledge and understanding with you.