diff --git a/cmake/nuget_helpers.cmake b/cmake/nuget_helpers.cmake
new file mode 100644
index 0000000000..62a222390d
--- /dev/null
+++ b/cmake/nuget_helpers.cmake
@@ -0,0 +1,57 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+cmake_minimum_required(VERSION 3.0)
+
+# Determines the version of a native nuget package from the root packages.config.
+#
+# id : package id
+# out : name of variable to set result
+function(pkg_version id out packages_config)
+ file(READ ${packages_config} packages_config_contents)
+ string(REGEX MATCH "package[ ]*id[ ]*=[ ]*\"${id}\"" found_package_id ${packages_config_contents})
+ if (NOT(found_package_id))
+ message(FATAL_ERROR "Could not find '${id}' in packages.config!")
+ endif()
+
+ set(pattern ".*id[ ]*=[ ]*\"${id}\"[ ]+version=\"([0-9a-zA-Z\\.-]+)\"[ ]+targetFramework.*")
+ string(REGEX REPLACE ${pattern} "\\1" version ${packages_config_contents})
+ set(${out} ${version} PARENT_SCOPE)
+endfunction()
+
+# Downloads the nuget packages based on packages.config
+function(
+ add_fetch_nuget_target
+ nuget_target # Target to be written to
+ target_dependency # The file in the nuget package that is needed
+)
+ # Pull down the nuget packages
+ if (NOT(MSVC) OR NOT(WIN32))
+ message(FATAL_ERROR "NuGet packages are only supported for MSVC on Windows.")
+ endif()
+
+ # Retrieve the latest version of nuget
+ include(ExternalProject)
+ ExternalProject_Add(nuget
+ PREFIX nuget
+ URL "https://dist.nuget.org/win-x86-commandline/v5.3.0/nuget.exe"
+ DOWNLOAD_NO_EXTRACT 1
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ UPDATE_COMMAND ""
+ INSTALL_COMMAND "")
+
+ set(NUGET_CONFIG ${PROJECT_SOURCE_DIR}/../NuGet.config)
+ set(PACKAGES_CONFIG ${PROJECT_SOURCE_DIR}/../packages.config)
+ get_filename_component(PACKAGES_DIR ${CMAKE_CURRENT_BINARY_DIR}/../packages ABSOLUTE)
+
+ # Restore nuget packages
+ add_custom_command(
+ OUTPUT ${target_dependency}
+ DEPENDS ${PACKAGES_CONFIG} ${NUGET_CONFIG}
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/nuget/src/nuget restore ${PACKAGES_CONFIG} -PackagesDirectory ${PACKAGES_DIR} -ConfigFile ${NUGET_CONFIG}
+ VERBATIM)
+
+ add_custom_target(${nuget_target} DEPENDS ${target_dependency})
+ add_dependencies(${nuget_target} nuget)
+endfunction()
\ No newline at end of file
diff --git a/cmake/winml.cmake b/cmake/winml.cmake
index 82f7541f6d..7946794f31 100644
--- a/cmake/winml.cmake
+++ b/cmake/winml.cmake
@@ -9,6 +9,7 @@ include(precompiled_header.cmake)
include(target_delayload.cmake)
include(winml_sdk_helpers.cmake)
include(winml_cppwinrt.cmake)
+include(nuget_helpers.cmake)
# get the current nuget sdk kit directory
get_sdk(sdk_folder sdk_version)
@@ -26,6 +27,22 @@ set(winml_lib_api_ort_dir ${REPO_ROOT}/winml/lib/api.ort)
set(winml_lib_common_dir ${REPO_ROOT}/winml/lib/common)
set(winml_lib_telemetry_dir ${REPO_ROOT}/winml/lib/telemetry)
+# Retrieve the version of cppwinrt nuget
+pkg_version(
+ Microsoft.Windows.CppWinRT
+ CppWinRT_version
+ ${PROJECT_SOURCE_DIR}/../packages.config
+)
+
+# Override and use the the cppwinrt from NuGet package as opposed to the one in the SDK.
+set(winml_CPPWINRT_EXE_PATH_OVERRIDE ${CMAKE_CURRENT_BINARY_DIR}/../packages/Microsoft.Windows.CppWinRT.${CppWinRT_version}/bin/cppwinrt.exe)
+
+# add custom target to fetch the nugets
+add_fetch_nuget_target(
+ RESTORE_NUGET_PACKAGES # target name
+ winml_CPPWINRT_EXE_PATH_OVERRIDE # cppwinrt is the target package
+ )
+
set(winml_is_inbox OFF)
if (onnxruntime_WINML_NAMESPACE_OVERRIDE)
set(output_name "${onnxruntime_WINML_NAMESPACE_OVERRIDE}.AI.MachineLearning")
@@ -77,6 +94,7 @@ add_generate_cppwinrt_sdk_headers_target(
${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include # output folder relative to CMAKE_BINARY_DIR where the generated sdk will be placed in the
${target_folder} # folder where this target will be placed
)
+add_dependencies(winml_sdk_cppwinrt RESTORE_NUGET_PACKAGES)
# generate winml headers from idl
target_cppwinrt(winml_api
@@ -89,6 +107,7 @@ target_cppwinrt(winml_api
"${winml_midl_defines}" # the midl compiler defines
${winml_api_use_ns_prefix} # set ns_prefix
)
+add_dependencies(winml_api RESTORE_NUGET_PACKAGES)
# generate winml.experimental headers from idl
target_cppwinrt(winml_api_experimental
@@ -101,6 +120,7 @@ target_cppwinrt(winml_api_experimental
${winml_midl_defines} # the midl compiler defines
${winml_api_use_ns_prefix} # set ns_prefix
)
+add_dependencies(winml_api_experimental RESTORE_NUGET_PACKAGES)
target_midl(winml_api_native
${idl_native} # winml native idl to compile
@@ -110,6 +130,7 @@ target_midl(winml_api_native
${target_folder} # the folder this target will be placed under
"${winml_midl_defines}" # the midl compiler defines
)
+add_dependencies(winml_api_native RESTORE_NUGET_PACKAGES)
target_midl(winml_api_native_internal
${idl_native_internal} # winml internal native idl to compile
@@ -119,6 +140,7 @@ target_midl(winml_api_native_internal
${target_folder} # the folder this target will be placed under
"${winml_midl_defines}" # the midl compiler defines
)
+add_dependencies(winml_api_native_internal RESTORE_NUGET_PACKAGES)
###########################
# Add winml_lib_telemetry
diff --git a/packages.config b/packages.config
index cf2b71e61a..c78c556bfd 100644
--- a/packages.config
+++ b/packages.config
@@ -1,5 +1,6 @@
-
+
+
diff --git a/winml/dll/module.cpp b/winml/dll/module.cpp
index de6820bdca..867edd9970 100644
--- a/winml/dll/module.cpp
+++ b/winml/dll/module.cpp
@@ -4,7 +4,6 @@
#include "pch.h"
#include
#include
-
#include "LearningModelDevice.h"
#include "OnnxruntimeProvider.h"
#include "Dummy.h"
@@ -92,9 +91,7 @@ STDAPI DllCanUnloadNow() {
STDAPI DllGetExperimentalActivationFactory(void* classId, void** factory) noexcept {
try {
*factory = nullptr;
- uint32_t length{};
- wchar_t const* const buffer = WINRT_WindowsGetStringRawBuffer(classId, &length);
- std::wstring_view const name{buffer, length};
+ std::wstring_view const name{*reinterpret_cast(&classId)};
auto requal = [](std::wstring_view const& left, std::wstring_view const& right) noexcept {
return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend());
diff --git a/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp b/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp
index f4b33c995a..53d2b1d67f 100644
--- a/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp
+++ b/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp
@@ -6,8 +6,9 @@
#include "OnnxruntimeErrors.h"
#include "core/platform/windows/TraceLoggingConfig.h"
#include
-
#include
+#include
+#include
using namespace _winml;
@@ -190,6 +191,18 @@ static void __stdcall WinmlOrtProfileEventCallback(const OrtProfilerEventRecord*
}
}
+static void OnSuspending(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::ApplicationModel::SuspendingEventArgs const& args) {
+ telemetry_helper.LogWinMLSuspended();
+}
+
+void OnnxruntimeEnvironment::RegisterSuspendHandler() {
+ try {
+ auto suspend_event_handler = winrt::Windows::Foundation::EventHandler(&OnSuspending);
+ suspend_token_ = winrt::Windows::ApplicationModel::Core::CoreApplication::Suspending(suspend_event_handler);
+ } catch (...) {
+ } //Catch in case CoreApplication cannot be found for non-UWP executions
+}
+
OnnxruntimeEnvironment::OnnxruntimeEnvironment(const OrtApi* ort_api) : ort_env_(nullptr, nullptr) {
OrtEnv* ort_env = nullptr;
THROW_IF_NOT_OK_MSG(ort_api->CreateEnv(OrtLoggingLevel::ORT_LOGGING_LEVEL_VERBOSE, "Default", &ort_env),
@@ -204,6 +217,15 @@ OnnxruntimeEnvironment::OnnxruntimeEnvironment(const OrtApi* ort_api) : ort_env_
ort_api);
THROW_IF_NOT_OK_MSG(winml_adapter_api->OverrideSchema(), ort_api);
+
+ // Register suspend handler for UWP applications
+ RegisterSuspendHandler();
+}
+
+OnnxruntimeEnvironment::~OnnxruntimeEnvironment() {
+ if (suspend_token_) {
+ winrt::Windows::ApplicationModel::Core::CoreApplication::Suspending(suspend_token_);
+ }
}
HRESULT OnnxruntimeEnvironment::GetOrtEnvironment(_Out_ OrtEnv** ort_env) {
diff --git a/winml/lib/Api.Ort/OnnxruntimeEnvironment.h b/winml/lib/Api.Ort/OnnxruntimeEnvironment.h
index 10df3aec6c..a1b9657737 100644
--- a/winml/lib/Api.Ort/OnnxruntimeEnvironment.h
+++ b/winml/lib/Api.Ort/OnnxruntimeEnvironment.h
@@ -11,12 +11,16 @@ namespace _winml {
class OnnxruntimeEnvironment {
public:
OnnxruntimeEnvironment(const OrtApi* ort_api);
-
+ ~OnnxruntimeEnvironment();
HRESULT GetOrtEnvironment(_Out_ OrtEnv** ert_env);
HRESULT EnableDebugOutput(bool is_enabled);
+ private:
+ void RegisterSuspendHandler();
+
private:
UniqueOrtEnv ort_env_;
+ winrt::event_token suspend_token_;
};
const OrtApi* GetVersionedOrtApi();
diff --git a/winml/lib/Common/inc/WinMLTelemetryHelper.h b/winml/lib/Common/inc/WinMLTelemetryHelper.h
index 7e3d025a09..87eabaa875 100644
--- a/winml/lib/Common/inc/WinMLTelemetryHelper.h
+++ b/winml/lib/Common/inc/WinMLTelemetryHelper.h
@@ -83,6 +83,7 @@ class WinMLTelemetryHelper {
}
void LogWinMLShutDown();
+ void LogWinMLSuspended();
void LogRuntimeError(HRESULT hr, std::string message, PCSTR file, PCSTR function, int line);
void LogRuntimeError(HRESULT hr, PCSTR message, PCSTR file, PCSTR function, int line);
void LogRegisterOperatorKernel(
diff --git a/winml/lib/Telemetry/WinMLTelemetryHelper.cpp b/winml/lib/Telemetry/WinMLTelemetryHelper.cpp
index 20e35fc61b..5ba7eec8b1 100644
--- a/winml/lib/Telemetry/WinMLTelemetryHelper.cpp
+++ b/winml/lib/Telemetry/WinMLTelemetryHelper.cpp
@@ -28,6 +28,16 @@ void WinMLTelemetryHelper::LogWinMLShutDown() {
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES));
}
+void WinMLTelemetryHelper::LogWinMLSuspended() {
+ WinMLTraceLoggingWrite(
+ provider_,
+ "WinMLSuspended",
+ TraceLoggingKeyword(WINML_PROVIDER_KEYWORD_DEFAULT),
+ TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance),
+ TraceLoggingInt32(runtime_session_id_, "runtimeSessionId"),
+ TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES));
+}
+
void WinMLTelemetryHelper::LogRuntimeError(HRESULT hr, PCSTR message, PCSTR file, PCSTR function, int line) {
if (!telemetry_enabled_)
return;