commit 095b221473deb749b7d20e04d125644a049579d1 parent 542759707d980a1068145283b821568bc45593c7 Author: JohnMcPMS <johnmcp@microsoft.com> Date: Wed, 14 Aug 2024 14:57:51 -0700 Create public sample (#4734) ## Change Copy the current dev tool, COM calling application into a new location and update significantly with the goal of being a public sample of usage. Cleaned up the code and tried to include more error handling and commenting. Major changes to the UX: - Removed the dev switch as this is intended as a public sample - Added example search options selection - Add `Upgrade` button so that function could be called as well - Add `Uninstall` button for installed packages - Disconnected installed and active operation lists from catalog selection and package search Major change to DevX: - Move to using the OOP COM nuget package - This isn't ready for use yet, as the OOP activation dll isn't available in a public version yet and we are still working on the exact shape of that update. Diffstat:
24 files changed, 1830 insertions(+), 0 deletions(-)
diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller.sln b/samples/WinGetUWPCaller/WinGetUWPCaller.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30704.19 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinGetUWPCaller", "WinGetUWPCaller\WinGetUWPCaller.vcxproj", "{37F1FD2A-4D63-45A0-82AA-66EF126CB322}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|ARM64.Build.0 = Debug|ARM64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|x64.ActiveCfg = Debug|x64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|x64.Build.0 = Debug|x64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|x64.Deploy.0 = Debug|x64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|x86.ActiveCfg = Debug|Win32 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|x86.Build.0 = Debug|Win32 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Debug|x86.Deploy.0 = Debug|Win32 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|ARM64.ActiveCfg = Release|ARM64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|ARM64.Build.0 = Release|ARM64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|ARM64.Deploy.0 = Release|ARM64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|x64.ActiveCfg = Release|x64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|x64.Build.0 = Release|x64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|x64.Deploy.0 = Release|x64 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|x86.ActiveCfg = Release|Win32 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|x86.Build.0 = Release|Win32 + {37F1FD2A-4D63-45A0-82AA-66EF126CB322}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D7D1DE2E-A7C1-4FB3-A191-C848562A3EBD} + EndGlobalSection +EndGlobal diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/ActivePackageView.cpp b/samples/WinGetUWPCaller/WinGetUWPCaller/ActivePackageView.cpp @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "ActivePackageView.h" +#include "ActivePackageView.g.cpp" +#include <winrt/Windows.UI.Core.h> + +namespace winrt::WinGetUWPCaller::implementation +{ + Microsoft::Management::Deployment::CatalogPackage ActivePackageView::Package() + { + return m_package; + } + + void ActivePackageView::Package(Microsoft::Management::Deployment::CatalogPackage const& value) + { + m_package = value; + } + + ActivePackageView::AsyncOperation_t ActivePackageView::AsyncOperation() + { + return m_asyncOperation; + } + + Windows::Foundation::IAsyncAction UpdateUIProgress( + Microsoft::Management::Deployment::InstallProgress progress, + WinGetUWPCaller::ActivePackageView view) + { + co_await resume_foreground(view.Dispatcher()); + view.Progress(progress.DownloadProgress * 100); + } + + void ActivePackageView::AsyncOperation(ActivePackageView::AsyncOperation_t const& value) + { + m_asyncOperation = value; + m_asyncOperation.Progress([=]( + ActivePackageView::AsyncOperation_t const& /* sender */, + Microsoft::Management::Deployment::InstallProgress const& progress) + { + UpdateUIProgress(progress, *this); + }); + } + + double ActivePackageView::Progress() + { + return m_progress; + } + + void ActivePackageView::Progress(double value) + { + if (m_progress != value) + { + m_progress = value; + m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Progress" }); + } + } + + hstring ActivePackageView::StatusText() + { + return m_text; + } + + void ActivePackageView::StatusText(hstring const& value) + { + m_text = value; + } + + Windows::UI::Core::CoreDispatcher ActivePackageView::Dispatcher() + { + return m_dispatcher; + } + + void ActivePackageView::Dispatcher(Windows::UI::Core::CoreDispatcher const& value) + { + m_dispatcher = value; + } + + event_token ActivePackageView::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler) + { + return m_propertyChanged.add(handler); + } + + void ActivePackageView::PropertyChanged(event_token const& token) + { + m_propertyChanged.remove(token); + } +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/ActivePackageView.h b/samples/WinGetUWPCaller/WinGetUWPCaller/ActivePackageView.h @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "ActivePackageView.g.h" + +namespace winrt::WinGetUWPCaller::implementation +{ + struct ActivePackageView : ActivePackageViewT<ActivePackageView> + { + using AsyncOperation_t = Windows::Foundation::IAsyncOperationWithProgress<Microsoft::Management::Deployment::InstallResult, Microsoft::Management::Deployment::InstallProgress>; + + ActivePackageView() = default; + + Microsoft::Management::Deployment::CatalogPackage Package(); + void Package(Microsoft::Management::Deployment::CatalogPackage const& value); + AsyncOperation_t AsyncOperation(); + void AsyncOperation(AsyncOperation_t const& value); + double Progress(); + void Progress(double value); + hstring StatusText(); + void StatusText(hstring const& value); + Windows::UI::Core::CoreDispatcher Dispatcher(); + void Dispatcher(Windows::UI::Core::CoreDispatcher const& value); + event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& value); + void PropertyChanged(event_token const& token); + + private: + Microsoft::Management::Deployment::CatalogPackage m_package{ nullptr }; + AsyncOperation_t m_asyncOperation{ nullptr }; + double m_progress = 0; + hstring m_text; + Windows::UI::Core::CoreDispatcher m_dispatcher{ nullptr }; + event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged; + }; +} + +namespace winrt::WinGetUWPCaller::factory_implementation +{ + struct ActivePackageView : ActivePackageViewT<ActivePackageView, implementation::ActivePackageView> + { + }; +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/App.cpp b/samples/WinGetUWPCaller/WinGetUWPCaller/App.cpp @@ -0,0 +1,121 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" + +#include "App.h" +#include "MainPage.h" + +using namespace winrt; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::Foundation; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Navigation; +using namespace WinGetUWPCaller; +using namespace WinGetUWPCaller::implementation; + +/// <summary> +/// Initializes the singleton application object. This is the first line of authored code +/// executed, and as such is the logical equivalent of main() or WinMain(). +/// </summary> +App::App() +{ + InitializeComponent(); + Suspending({ this, &App::OnSuspending }); + +#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e) + { + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); +#endif +} + +/// <summary> +/// Invoked when the application is launched normally by the end user. Other entry points +/// will be used such as when the application is launched to open a specific file. +/// </summary> +/// <param name="e">Details about the launch request and process.</param> +void App::OnLaunched(LaunchActivatedEventArgs const& e) +{ + Frame rootFrame{ nullptr }; + auto content = Window::Current().Content(); + if (content) + { + rootFrame = content.try_as<Frame>(); + } + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == nullptr) + { + // Create a Frame to act as the navigation context and associate it with + // a SuspensionManager key + rootFrame = Frame(); + + rootFrame.NavigationFailed({ this, &App::OnNavigationFailed }); + + if (e.PreviousExecutionState() == ApplicationExecutionState::Terminated) + { + // Restore the saved session state only when appropriate, scheduling the + // final launch steps after the restore is complete + } + + if (e.PrelaunchActivated() == false) + { + if (rootFrame.Content() == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(xaml_typename<WinGetUWPCaller::MainPage>(), box_value(e.Arguments())); + } + // Place the frame in the current Window + Window::Current().Content(rootFrame); + // Ensure the current window is active + Window::Current().Activate(); + } + } + else + { + if (e.PrelaunchActivated() == false) + { + if (rootFrame.Content() == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(xaml_typename<WinGetUWPCaller::MainPage>(), box_value(e.Arguments())); + } + // Ensure the current window is active + Window::Current().Activate(); + } + } +} + +/// <summary> +/// Invoked when application execution is being suspended. Application state is saved +/// without knowing whether the application will be terminated or resumed with the contents +/// of memory still intact. +/// </summary> +/// <param name="sender">The source of the suspend request.</param> +/// <param name="e">Details about the suspend request.</param> +void App::OnSuspending([[maybe_unused]] IInspectable const& sender, [[maybe_unused]] SuspendingEventArgs const& e) +{ + // Save application state and stop any background activity +} + +/// <summary> +/// Invoked when Navigation to a certain page fails +/// </summary> +/// <param name="sender">The Frame which failed navigation</param> +/// <param name="e">Details about the navigation failure</param> +void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e) +{ + throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name); +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/App.h b/samples/WinGetUWPCaller/WinGetUWPCaller/App.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "App.xaml.g.h" + +namespace winrt::WinGetUWPCaller::implementation +{ + struct App : AppT<App> + { + App(); + + void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&); + void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); + void OnNavigationFailed(IInspectable const&, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const&); + }; +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/App.idl b/samples/WinGetUWPCaller/WinGetUWPCaller/App.idl @@ -0,0 +1,3 @@ +namespace WinGetUWPCaller +{ +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/App.xaml b/samples/WinGetUWPCaller/WinGetUWPCaller/App.xaml @@ -0,0 +1,9 @@ +<!-- Copyright (c) Microsoft Corporation. + Licensed under the MIT License. --> +<Application + x:Class="WinGetUWPCaller.App" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="using:WinGetUWPCaller"> + +</Application> diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/LockScreenLogo.scale-200.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/LockScreenLogo.scale-200.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/SplashScreen.scale-200.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/SplashScreen.scale-200.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Square150x150Logo.scale-200.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Square150x150Logo.scale-200.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Square44x44Logo.scale-200.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Square44x44Logo.scale-200.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Square44x44Logo.targetsize-24_altform-unplated.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/StoreLogo.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/StoreLogo.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Wide310x150Logo.scale-200.png b/samples/WinGetUWPCaller/WinGetUWPCaller/Assets/Wide310x150Logo.scale-200.png Binary files differ. diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.cpp b/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.cpp @@ -0,0 +1,951 @@ +#include "pch.h" +#include "MainPage.h" +#include "MainPage.g.cpp" + +#include <winrt/Microsoft.Management.Deployment.h> + +using namespace std::chrono_literals; +using namespace std::string_view_literals; +using namespace winrt::Microsoft::Management::Deployment; + +namespace winrt +{ + using namespace Windows::UI::Xaml; + using namespace Windows::Foundation; + using namespace Windows::Foundation::Collections; +} + +namespace winrt::WinGetUWPCaller::implementation +{ + namespace + { + std::wstring ConvertExceptionToStatusString(std::wstring_view context, std::exception_ptr exceptionPtr) + { + std::wostringstream result; + + try + { + std::rethrow_exception(exceptionPtr); + } + catch (const winrt::hresult_error& error) + { + result << context << L" :: " << L"0x" << std::hex << std::setw(8) << std::setfill(L'0') << error.code() << L": " << static_cast<std::wstring_view>(error.message()); + } + catch (const std::exception& exception) + { + result << context << L" :: " << exception.what(); + } + catch (...) + { + result << context << L" :: Unknown exception"; + } + + return std::move(result).str(); + } + + template <typename Operation> + std::wstring RunAndReturnStatus(std::wstring_view context, Operation&& operation) + { + try + { + operation(); + } + catch (...) + { + return ConvertExceptionToStatusString(context, std::current_exception()); + } + + return {}; + } + + // Helper object to control button states and status text. + struct BackgroundActionData + { + // This object should be constructed on the foreground thread. + // disabledButtons will be disabled during the operation. + // enabledButtons will be enabled during the operation. + // statusText will be updated with the result. + BackgroundActionData( + std::initializer_list<Windows::UI::Xaml::Controls::Button> disabledButtons, + Windows::UI::Xaml::Controls::TextBlock statusText) : + m_disabledButtons(disabledButtons), + m_statusText(statusText) + { + if (m_disabledButtons.empty()) + { + throw std::exception("Must specify at least one disabled button."); + } + + for (const auto& button : m_disabledButtons) + { + button.IsEnabled(false); + } + + m_statusText.Text(L""); + } + + BackgroundActionData( + std::initializer_list<Windows::UI::Xaml::Controls::Button> disabledButtons, + std::initializer_list<Windows::UI::Xaml::Controls::Button> enabledButtons, + Windows::UI::Xaml::Controls::TextBlock statusText) : + BackgroundActionData(disabledButtons, statusText) + { + m_enabledButtons = enabledButtons; + for (const auto& button : m_enabledButtons) + { + button.IsEnabled(true); + } + } + + // This should be run on the foreground thread. + void Finalize() const + { + for (const auto& button : m_disabledButtons) + { + button.IsEnabled(true); + } + + for (const auto& button : m_enabledButtons) + { + button.IsEnabled(false); + } + + m_statusText.Text(m_status); + } + + template <typename Operation> + void RunAndCatchStatus(std::wstring_view context, Operation&& operation) + { + if (m_status.empty()) + { + m_status = RunAndReturnStatus(context, operation); + } + } + + void Status(std::wstring&& value) + { + m_status = std::move(value); + } + + bool Successful() const + { + return m_status.empty(); + } + + Windows::UI::Core::CoreDispatcher Dispatcher() const + { + return m_disabledButtons[0].Dispatcher(); + } + + private: + std::vector<Windows::UI::Xaml::Controls::Button> m_disabledButtons; + std::vector<Windows::UI::Xaml::Controls::Button> m_enabledButtons; + Windows::UI::Xaml::Controls::TextBlock m_statusText; + std::wstring m_status; + }; + + std::wstring MakeCompactByteString(uint64_t bytes) + { + static constexpr std::array<std::wstring_view, 4> s_sizeStrings = { L"B"sv, L"KB"sv, L"MB"sv, L"GB"sv }; + static constexpr size_t s_sizeIncrement = 1000; + + size_t sizeIndex = 0; + while (sizeIndex < s_sizeStrings.size() && bytes > s_sizeIncrement) + { + sizeIndex += 1; + bytes /= s_sizeIncrement; + } + + return std::to_wstring(bytes).append(L" ").append(s_sizeStrings[sizeIndex]); + } + } + + MainPage::MainPage() + { + InitializeComponent(); + m_packageCatalogs = winrt::single_threaded_observable_vector<PackageCatalogReference>(); + m_installedPackages = winrt::single_threaded_observable_vector<CatalogPackage>(); + m_activePackageViews = winrt::single_threaded_observable_vector<WinGetUWPCaller::ActivePackageView>(); + } + + Windows::Foundation::Collections::IObservableVector<Microsoft::Management::Deployment::PackageCatalogReference> MainPage::PackageCatalogs() + { + return m_packageCatalogs; + } + + Windows::Foundation::Collections::IObservableVector<Microsoft::Management::Deployment::CatalogPackage> MainPage::InstalledPackages() + { + return m_installedPackages; + } + + Windows::Foundation::Collections::IObservableVector<WinGetUWPCaller::ActivePackageView> MainPage::ActivePackages() + { + return m_activePackageViews; + } + + void MainPage::LoadCatalogsButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + LoadCatalogsAsync(); + } + + void MainPage::CatalogSelectionChangedHandler(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::RoutedEventArgs const&) + { + m_catalog = nullptr; + } + + void MainPage::SearchButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + FindPackageAsync(); + } + + void MainPage::InstallButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + if (m_packageOperation == nullptr || m_packageOperation.Status() != AsyncStatus::Started) + { + InstallOrUpgradeAsync(false); + } + } + + void MainPage::UpgradeButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + if (m_packageOperation == nullptr || m_packageOperation.Status() != AsyncStatus::Started) + { + InstallOrUpgradeAsync(true); + } + } + + void MainPage::DownloadButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + if (m_packageOperation == nullptr || m_packageOperation.Status() != AsyncStatus::Started) + { + DownloadAsync(); + } + } + + void MainPage::CancelButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + if (m_packageOperation && m_packageOperation.Status() == AsyncStatus::Started) + { + m_packageOperation.Cancel(); + } + } + + void MainPage::RefreshInstalledButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + GetInstalledPackagesAsync(); + } + + void MainPage::UninstallButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + UninstallAsync(); + } + + void MainPage::RefreshActiveButtonClickHandler(IInspectable const&, RoutedEventArgs const&) + { + GetActivePackagesAsync(); + } + + std::wstring MainPage::EnsurePackageManager(bool forceRecreate) + { + std::lock_guard<std::mutex> lock{ m_packageManagerMutex }; + + std::wstring result; + + if (!m_packageManager || forceRecreate) + { + result = RunAndReturnStatus(L"Create PackageManager", [&]() { + m_packageManager = PackageManager{}; + }); + } + + return result; + } + + IAsyncAction MainPage::LoadCatalogsAsync() + { + BackgroundActionData actionData{ { loadCatalogsButton() }, catalogStatusText() }; + + co_await winrt::resume_background(); + + actionData.Status(EnsurePackageManager(true)); + + decltype(m_packageManager.GetPackageCatalogs()) catalogs{ nullptr }; + actionData.RunAndCatchStatus(L"Load Catalogs", [&]() { + catalogs = m_packageManager.GetPackageCatalogs(); + }); + + co_await winrt::resume_foreground(actionData.Dispatcher()); + + m_packageCatalogs.Clear(); + + if (catalogs) + { + for (auto const catalog : catalogs) + { + m_packageCatalogs.Append(catalog); + } + } + + actionData.Finalize(); + } + + IAsyncAction MainPage::FindPackageAsync() + { + hstring queryInput = queryTextBox().Text(); + auto selectedItems = catalogsListBox().SelectedItems(); + int32_t searchType = searchField().SelectedIndex(); + PackageCatalog catalog = m_catalog; + + BackgroundActionData actionData{ { searchButton() }, operationStatusText() }; + + co_await winrt::resume_background(); + + actionData.Status(EnsurePackageManager()); + + if (!catalog) + { + actionData.RunAndCatchStatus(L"Connect catalog(s)", [&]() { + PackageCatalogReference catalogReference{ nullptr }; + + if (selectedItems.Size() == 0) + { + // If no items are selected, we use all available catalogs. + CreateCompositePackageCatalogOptions createCompositePackageCatalogOptions; + createCompositePackageCatalogOptions.CompositeSearchBehavior(CompositeSearchBehavior::RemotePackagesFromRemoteCatalogs); + + for (const auto& item : m_packageManager.GetPackageCatalogs()) + { + createCompositePackageCatalogOptions.Catalogs().Append(item); + } + + catalogReference = m_packageManager.CreateCompositePackageCatalog(createCompositePackageCatalogOptions); + } + else if (selectedItems.Size() == 1) + { + // If one items is selected, we can directly use this catalog. + catalogReference = selectedItems.GetAt(0).as<PackageCatalogReference>(); + } + else + { + // If multiple items are selected, we create a composite catalog using those catalogs. + CreateCompositePackageCatalogOptions createCompositePackageCatalogOptions; + createCompositePackageCatalogOptions.CompositeSearchBehavior(CompositeSearchBehavior::RemotePackagesFromRemoteCatalogs); + + for (const auto& item : selectedItems) + { + createCompositePackageCatalogOptions.Catalogs().Append(item.as<PackageCatalogReference>()); + } + + catalogReference = m_packageManager.CreateCompositePackageCatalog(createCompositePackageCatalogOptions); + } + + ConnectResult connectResult{ catalogReference.Connect() }; + + switch (connectResult.Status()) + { + case ConnectResultStatus::Ok: break; + case ConnectResultStatus::CatalogError: throw std::exception{ "Catalog connection error." }; + case ConnectResultStatus::SourceAgreementsNotAccepted: throw std::exception{ "Required catalog agreements not accepted." }; + } + + catalog = connectResult.PackageCatalog(); + }); + } + + CatalogPackage package{ nullptr }; + + actionData.RunAndCatchStatus(L"Find package", [&]() { + FindPackagesOptions findPackagesOptions; + PackageMatchFilter filter; + + switch (searchType) + { + case 0: // Generic query + filter.Field(PackageMatchField::CatalogDefault); + filter.Option(PackageFieldMatchOption::ContainsCaseInsensitive); + break; + case 1: // Identifier (case-insensitive) + filter.Field(PackageMatchField::Id); + filter.Option(PackageFieldMatchOption::EqualsCaseInsensitive); + break; + case 2: // Name (substring) + filter.Field(PackageMatchField::Name); + filter.Option(PackageFieldMatchOption::ContainsCaseInsensitive); + break; + } + + filter.Value(queryInput); + findPackagesOptions.Selectors().Append(filter); + FindPackagesResult findPackagesResult = catalog.FindPackages(findPackagesOptions); + + winrt::IVectorView<MatchResult> matches = findPackagesResult.Matches(); + if (matches.Size() == 0) + { + throw std::exception{ "No package found matching input" }; + } + else if (matches.Size() > 1) + { + throw std::exception{ "Multiple packages found matching input; refine query." }; + } + else + { + package = matches.GetAt(0).CatalogPackage(); + } + }); + + if (package) + { + // Display the package name using the user's default localization information. + std::wostringstream stream; + stream << L"Found package: " << + static_cast<std::wstring_view>(package.DefaultInstallVersion().GetCatalogPackageMetadata().PackageName()) << L" [" << + static_cast<std::wstring_view>(package.Id()) << L"]"; + actionData.Status(std::move(stream).str()); + } + + co_await winrt::resume_foreground(actionData.Dispatcher()); + + m_catalog = catalog; + m_package = package; + + bool operationButtonsEnabled = static_cast<bool>(m_package); + installButton().IsEnabled(operationButtonsEnabled); + upgradeButton().IsEnabled(operationButtonsEnabled); + downloadButton().IsEnabled(operationButtonsEnabled); + + actionData.Finalize(); + } + + IAsyncAction MainPage::InstallOrUpgradeAsync(bool upgrade) + { + PackageManager packageManager = m_packageManager; + CatalogPackage package = m_package; + auto progressBar = operationProgressBar(); + auto statusText = operationStatusText(); + + BackgroundActionData actionData{ { installButton(), upgradeButton(), downloadButton() }, { cancelButton() }, statusText }; + + co_await winrt::resume_background(); + + Windows::Foundation::IAsyncOperationWithProgress<Deployment::InstallResult, Deployment::InstallProgress> packageOperation; + + actionData.RunAndCatchStatus(L"Begin install", [&]() { + InstallOptions installOptions; + + // Passing PackageInstallScope::User causes the install to fail if there's no installer that supports that. + installOptions.PackageInstallScope(PackageInstallScope::Any); + installOptions.PackageInstallMode(PackageInstallMode::Silent); + + if (upgrade) + { + packageOperation = packageManager.UpgradePackageAsync(package, installOptions); + } + else + { + packageOperation = packageManager.InstallPackageAsync(package, installOptions); + } + }); + + actionData.Dispatcher().RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, + [packageOperation, this]() { m_packageOperation = packageOperation; }); + + actionData.RunAndCatchStatus(L"Set progress handler", [&]() { + packageOperation.Progress([&]( + IAsyncOperationWithProgress<InstallResult, InstallProgress> const& /* sender */, + InstallProgress const& progress) + { + actionData.Dispatcher().RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, + [progressBar, statusText, progress]() { + progressBar.Value(progress.DownloadProgress * 100); + + switch (progress.State) + { + case PackageInstallProgressState::Queued: + statusText.Text(L"Queued"); + break; + case PackageInstallProgressState::Downloading: + { + std::wstring downloadText{ L"Downloaded " }; + downloadText += MakeCompactByteString(progress.BytesDownloaded) + L" of " + MakeCompactByteString(progress.BytesRequired); + statusText.Text(downloadText); + } + break; + case PackageInstallProgressState::Installing: + statusText.Text(L"Installer running"); + progressBar.IsIndeterminate(true); + break; + case PackageInstallProgressState::PostInstall: + statusText.Text(L"Post install bookkeeping"); + break; + case PackageInstallProgressState::Finished: + statusText.Text(L"Done"); + progressBar.IsIndeterminate(false); + break; + default: + statusText.Text(L""); + } + }); + }); + }); + + InstallResult installResult{ nullptr }; + + actionData.RunAndCatchStatus(L"Install", [&]() { + installResult = packageOperation.get(); + }); + + if (packageOperation && packageOperation.Status() == AsyncStatus::Canceled) + { + actionData.Status(L"Cancelled"); + } + else if (installResult) + { + // Error handling for the installResult is done by first examining the Status. + // Any status value other than Ok will have additional error detail in the + // ExtendedErrorCode property. This HRESULT value will typically (but not always) + // have the Windows Package Manager facility value (0xA15). The symbolic names and + // meanings of these error codes can be found at: + // https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-manager/winget/returnCodes.md + // or by using the winget CLI: + // > winget error 0x8A150049 + // > winget error -- -2146762487 + switch (installResult.Status()) + { + case InstallResultStatus::Ok: + actionData.Status(installResult.RebootRequired() ? L"Reboot required" : L"Done"); + break; + case InstallResultStatus::BlockedByPolicy: + // See installResult.ExtendedErrorCode for more detail. + // This is typically caused by system configuration applied by policy. + actionData.Status(L"Blocked by policy"); + break; + case InstallResultStatus::CatalogError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically an issue with an external service. + actionData.Status(L"Catalog error"); + break; + case InstallResultStatus::InternalError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically an issue with the Windows Package Manager code. + actionData.Status(L"Internal error"); + break; + case InstallResultStatus::InvalidOptions: + // See installResult.ExtendedErrorCode for more detail. + // This is caused by invalid input combinations. + actionData.Status(L"Invalid options"); + break; + case InstallResultStatus::DownloadError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically a transient network error. + actionData.Status(L"Download error"); + break; + case InstallResultStatus::InstallError: + // See installResult.ExtendedErrorCode and installResult.InstallerErrorCode for more detail. + // This is caused by an error in the installer or an issue with the system state. + // InstallerErrorCode is the value returned by the installer technology in use for the install + // attempt and may or may not be an HRESULT. + actionData.Status(L"Installation error"); + break; + case InstallResultStatus::ManifestError: + // See installResult.ExtendedErrorCode for more detail. + // This is an issue with the catalog providing the package. + actionData.Status(L"Manifest error"); + break; + case InstallResultStatus::NoApplicableInstallers: + // No applicable installers were available due the combination of the current system, + // user settings, and parameters provided to the install request. + actionData.Status(L"No applicable installers"); + break; + case InstallResultStatus::NoApplicableUpgrade: + // No upgrade was available due the combination of available versions, the current system, + // user settings, and parameters provided to the upgrade request. + actionData.Status(L"No applicable upgrade"); + break; + case InstallResultStatus::PackageAgreementsNotAccepted: + // The user has not accepted the agreements required by the package. + actionData.Status(L"Package agreements not accepted"); + break; + } + } + + // Switch back to ui thread context. + co_await winrt::resume_foreground(actionData.Dispatcher()); + + progressBar.IsIndeterminate(false); + + actionData.Finalize(); + } + + IAsyncAction MainPage::DownloadAsync() + { + hstring downloadDirectory = downloadDirectoryTextBox().Text(); + PackageManager packageManager = m_packageManager; + CatalogPackage package = m_package; + auto progressBar = operationProgressBar(); + auto statusText = operationStatusText(); + + BackgroundActionData actionData{ { installButton(), upgradeButton(), downloadButton() }, { cancelButton() }, statusText}; + + co_await winrt::resume_background(); + + Windows::Foundation::IAsyncOperationWithProgress<Deployment::DownloadResult, Deployment::PackageDownloadProgress> packageOperation; + + actionData.RunAndCatchStatus(L"Begin download", [&]() { + DownloadOptions downloadOptions; + + if (!downloadDirectory.empty()) + { + downloadOptions.DownloadDirectory(downloadDirectory); + } + + packageOperation = packageManager.DownloadPackageAsync(package, downloadOptions); + }); + + actionData.Dispatcher().RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, + [packageOperation, this]() { m_packageOperation = packageOperation; }); + + actionData.RunAndCatchStatus(L"Set progress handler", [&]() { + packageOperation.Progress([&]( + IAsyncOperationWithProgress<DownloadResult, PackageDownloadProgress> const& /* sender */, + PackageDownloadProgress const& progress) + { + actionData.Dispatcher().RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, + [progressBar, statusText, progress]() { + progressBar.Value(progress.DownloadProgress * 100); + + switch (progress.State) + { + case PackageDownloadProgressState::Queued: + statusText.Text(L"Queued"); + break; + case PackageDownloadProgressState::Downloading: + { + std::wstring downloadText{ L"Downloaded " }; + downloadText += MakeCompactByteString(progress.BytesDownloaded) + L" of " + MakeCompactByteString(progress.BytesRequired); + statusText.Text(downloadText); + } + break; + case PackageDownloadProgressState::Finished: + statusText.Text(L"Done"); + progressBar.IsIndeterminate(false); + break; + default: + statusText.Text(L""); + } + }); + }); + }); + + DownloadResult downloadResult{ nullptr }; + + actionData.RunAndCatchStatus(L"Download", [&]() { + downloadResult = packageOperation.get(); + }); + + if (packageOperation && packageOperation.Status() == AsyncStatus::Canceled) + { + actionData.Status(L"Cancelled"); + } + else if (downloadResult) + { + // Error handling for the downloadResult is done by first examining the Status. + // Any status value other than Ok will have additional error detail in the + // ExtendedErrorCode property. This HRESULT value will typically (but not always) + // have the Windows Package Manager facility value (0xA15). The symbolic names and + // meanings of these error codes can be found at: + // https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-manager/winget/returnCodes.md + // or by using the winget CLI: + // > winget error 0x8A150049 + // > winget error -- -2146762487 + switch (downloadResult.Status()) + { + case DownloadResultStatus::Ok: + actionData.Status(L"Done"); + break; + case DownloadResultStatus::BlockedByPolicy: + // See installResult.ExtendedErrorCode for more detail. + // This is typically caused by system configuration applied by policy. + actionData.Status(L"Blocked by policy"); + break; + case DownloadResultStatus::CatalogError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically an issue with an external service. + actionData.Status(L"Catalog error"); + break; + case DownloadResultStatus::InternalError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically an issue with the Windows Package Manager code. + actionData.Status(L"Internal error"); + break; + case DownloadResultStatus::InvalidOptions: + // See installResult.ExtendedErrorCode for more detail. + // This is caused by invalid input combinations. + actionData.Status(L"Invalid options"); + break; + case DownloadResultStatus::DownloadError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically a transient network error. + actionData.Status(L"Download error"); + break; + case DownloadResultStatus::ManifestError: + // See installResult.ExtendedErrorCode for more detail. + // This is an issue with the catalog providing the package. + actionData.Status(L"Manifest error"); + break; + case DownloadResultStatus::NoApplicableInstallers: + // No applicable installers were available due the combination of the current system, + // user settings, and parameters provided to the install request. + actionData.Status(L"No applicable installers"); + break; + case DownloadResultStatus::PackageAgreementsNotAccepted: + // The user has not accepted the agreements required by the package. + actionData.Status(L"Package agreements not accepted"); + break; + } + } + + // Switch back to ui thread context. + co_await winrt::resume_foreground(actionData.Dispatcher()); + + progressBar.IsIndeterminate(false); + + actionData.Finalize(); + } + + IAsyncAction MainPage::GetInstalledPackagesAsync() + { + BackgroundActionData actionData{ { refreshInstalledButton() }, installedStatusText() }; + + co_await winrt::resume_background(); + + actionData.Status(EnsurePackageManager()); + + PackageCatalog catalog{ nullptr }; + + actionData.RunAndCatchStatus(L"Connect installed catalog", [&]() { + PackageCatalogReference catalogReference = m_packageManager.GetLocalPackageCatalog(LocalPackageCatalog::InstalledPackages); + ConnectResult connectResult{ catalogReference.Connect() }; + + switch (connectResult.Status()) + { + case ConnectResultStatus::Ok: break; + case ConnectResultStatus::CatalogError: throw std::exception{ "Catalog connection error." }; + } + + catalog = connectResult.PackageCatalog(); + }); + + winrt::IVectorView<MatchResult> matches; + + actionData.RunAndCatchStatus(L"Find package", [&]() { + FindPackagesOptions findPackagesOptions; + FindPackagesResult findPackagesResult = catalog.FindPackages(findPackagesOptions); + + matches = findPackagesResult.Matches(); + }); + + co_await winrt::resume_foreground(actionData.Dispatcher()); + + m_installedPackages.Clear(); + + if (matches) + { + for (auto const& match : matches) + { + m_installedPackages.Append(match.CatalogPackage()); + } + } + + actionData.Finalize(); + } + + IAsyncAction MainPage::UninstallAsync() + { + PackageManager packageManager = m_packageManager; + + auto progressBar = uninstallProgressBar(); + auto statusText = uninstallStatusText(); + + IInspectable selectedValue = installedListBox().SelectedValue(); + CatalogPackage package{ nullptr }; + if (selectedValue) + { + package = selectedValue.as<CatalogPackage>(); + } + else + { + statusText.Text(L"Select a package to uninstall"); + co_return; + } + + BackgroundActionData actionData{ { uninstallButton() }, statusText }; + + co_await winrt::resume_background(); + + Windows::Foundation::IAsyncOperationWithProgress<Deployment::UninstallResult, Deployment::UninstallProgress> packageOperation; + + actionData.RunAndCatchStatus(L"Begin uninstall", [&]() { + UninstallOptions uninstallOptions; + + uninstallOptions.PackageUninstallScope(PackageUninstallScope::Any); + uninstallOptions.PackageUninstallMode(PackageUninstallMode::Silent); + + packageOperation = packageManager.UninstallPackageAsync(package, uninstallOptions); + }); + + actionData.RunAndCatchStatus(L"Set progress handler", [&]() { + packageOperation.Progress([&]( + IAsyncOperationWithProgress<UninstallResult, UninstallProgress> const& /* sender */, + UninstallProgress const& progress) + { + actionData.Dispatcher().RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, + [progressBar, statusText, progress]() { + progressBar.Value(progress.UninstallationProgress * 100); + + switch (progress.State) + { + case PackageUninstallProgressState::Queued: + statusText.Text(L"Queued"); + break; + case PackageUninstallProgressState::Uninstalling: + statusText.Text(L"Uninstaller running"); + progressBar.IsIndeterminate(true); + break; + case PackageUninstallProgressState::PostUninstall: + statusText.Text(L"Post uninstall bookkeeping"); + break; + case PackageUninstallProgressState::Finished: + statusText.Text(L"Done"); + progressBar.IsIndeterminate(false); + break; + default: + statusText.Text(L""); + } + }); + }); + }); + + UninstallResult uninstallResult{ nullptr }; + + actionData.RunAndCatchStatus(L"Uninstall", [&]() { + uninstallResult = packageOperation.get(); + }); + + if (packageOperation && packageOperation.Status() == AsyncStatus::Canceled) + { + actionData.Status(L"Cancelled"); + } + else if (uninstallResult) + { + // Error handling for the installResult is done by first examining the Status. + // Any status value other than Ok will have additional error detail in the + // ExtendedErrorCode property. This HRESULT value will typically (but not always) + // have the Windows Package Manager facility value (0xA15). The symbolic names and + // meanings of these error codes can be found at: + // https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-manager/winget/returnCodes.md + // or by using the winget CLI: + // > winget error 0x8A150049 + // > winget error -- -2146762487 + switch (uninstallResult.Status()) + { + case UninstallResultStatus::Ok: + actionData.Status(uninstallResult.RebootRequired() ? L"Reboot required" : L"Done"); + break; + case UninstallResultStatus::BlockedByPolicy: + // See installResult.ExtendedErrorCode for more detail. + // This is typically caused by system configuration applied by policy. + actionData.Status(L"Blocked by policy"); + break; + case UninstallResultStatus::CatalogError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically an issue with an external service. + actionData.Status(L"Catalog error"); + break; + case UninstallResultStatus::InternalError: + // See installResult.ExtendedErrorCode for more detail. + // This is typically an issue with the Windows Package Manager code. + actionData.Status(L"Internal error"); + break; + case UninstallResultStatus::InvalidOptions: + // See installResult.ExtendedErrorCode for more detail. + // This is caused by invalid input combinations. + actionData.Status(L"Invalid options"); + break; + case UninstallResultStatus::UninstallError: + // See installResult.ExtendedErrorCode and installResult.UninstallerErrorCode for more detail. + // This is caused by an error in the uninstaller or an issue with the system state. + // UninstallerErrorCode is the value returned by the uninstaller technology in use for the uninstall + // attempt and may or may not be an HRESULT. + actionData.Status(L"Uninstallation error"); + break; + case UninstallResultStatus::ManifestError: + // See installResult.ExtendedErrorCode for more detail. + // This is an issue with the catalog providing the package. + actionData.Status(L"Manifest error"); + break; + } + } + + // Switch back to ui thread context. + co_await winrt::resume_foreground(actionData.Dispatcher()); + + progressBar.IsIndeterminate(false); + + actionData.Finalize(); + } + + IAsyncAction MainPage::GetActivePackagesAsync() + { + BackgroundActionData actionData{ { activeRefreshButton() }, activeStatusText() }; + + co_await winrt::resume_background(); + + actionData.Status(EnsurePackageManager()); + + PackageCatalog catalog{ nullptr }; + + actionData.RunAndCatchStatus(L"Connect installed catalog", [&]() { + PackageCatalogReference catalogReference = m_packageManager.GetLocalPackageCatalog(LocalPackageCatalog::InstallingPackages); + ConnectResult connectResult{ catalogReference.Connect() }; + + switch (connectResult.Status()) + { + case ConnectResultStatus::Ok: break; + case ConnectResultStatus::CatalogError: throw std::exception{ "Catalog connection error." }; + } + + catalog = connectResult.PackageCatalog(); + }); + + winrt::IVectorView<MatchResult> matches; + + actionData.RunAndCatchStatus(L"Find package", [&]() { + FindPackagesOptions findPackagesOptions; + FindPackagesResult findPackagesResult = catalog.FindPackages(findPackagesOptions); + + matches = findPackagesResult.Matches(); + }); + + co_await winrt::resume_foreground(actionData.Dispatcher()); + + m_activePackageViews.Clear(); + + if (matches) + { + for (auto const& match : matches) + { + WinGetUWPCaller::ActivePackageView activeView; + activeView.Package(match.CatalogPackage()); + auto installOperation = m_packageManager.GetInstallProgress(activeView.Package(), nullptr); + if (installOperation) + { + activeView.Dispatcher(actionData.Dispatcher()); + activeView.AsyncOperation(installOperation); + m_activePackageViews.Append(activeView); + } + } + } + + actionData.Finalize(); + } +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.h b/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.h @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "MainPage.g.h" +#include "ActivePackageView.h" +#include <winrt\Microsoft.Management.Deployment.h> +#include <mutex> + +namespace Deployment = winrt::Microsoft::Management::Deployment; + +namespace winrt::WinGetUWPCaller::implementation +{ + struct MainPage : MainPageT<MainPage> + { + MainPage(); + + Windows::Foundation::Collections::IObservableVector<Deployment::PackageCatalogReference> PackageCatalogs(); + Windows::Foundation::Collections::IObservableVector<Deployment::CatalogPackage> InstalledPackages(); + Windows::Foundation::Collections::IObservableVector<WinGetUWPCaller::ActivePackageView> ActivePackages(); + + // Select Catalog(s) section + void LoadCatalogsButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void CatalogSelectionChangedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + + // Package Operations section + void SearchButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void InstallButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void UpgradeButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void DownloadButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void CancelButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + + // Installed Packages section + void RefreshInstalledButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void UninstallButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + + // Active Operations section + void RefreshActiveButtonClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + + private: + // Ensures that the package manager object exists; potentially recreating it if requested. + // Should be called from a background thread. + // Is thread-safe. + // Returns an error string if it fails. + std::wstring EnsurePackageManager(bool forceRecreate = false); + + // Select Catalog(s) section + Windows::Foundation::IAsyncAction LoadCatalogsAsync(); + + // Package Operations section + Windows::Foundation::IAsyncAction FindPackageAsync(); + Windows::Foundation::IAsyncAction InstallOrUpgradeAsync(bool upgrade); + Windows::Foundation::IAsyncAction DownloadAsync(); + + // Installed Packages section + Windows::Foundation::IAsyncAction GetInstalledPackagesAsync(); + Windows::Foundation::IAsyncAction UninstallAsync(); + + // Active Operations section + Windows::Foundation::IAsyncAction GetActivePackagesAsync(); + + // Member fields + Windows::Foundation::Collections::IObservableVector<Deployment::PackageCatalogReference> m_packageCatalogs; + Windows::Foundation::Collections::IObservableVector<Deployment::CatalogPackage> m_installedPackages; + Windows::Foundation::Collections::IObservableVector<WinGetUWPCaller::ActivePackageView> m_activePackageViews; + + std::mutex m_packageManagerMutex; + Deployment::PackageManager m_packageManager{ nullptr }; + Deployment::PackageCatalog m_catalog{ nullptr }; + Deployment::CatalogPackage m_package{ nullptr }; + Windows::Foundation::IAsyncInfo m_packageOperation; + }; +} + +namespace winrt::WinGetUWPCaller::factory_implementation +{ + struct MainPage : MainPageT<MainPage, implementation::MainPage> + { + }; +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.idl b/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.idl @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +namespace WinGetUWPCaller +{ + [default_interface] + runtimeclass ActivePackageView : Windows.UI.Xaml.Data.INotifyPropertyChanged + { + ActivePackageView(); + + Microsoft.Management.Deployment.CatalogPackage Package; + Windows.Foundation.IAsyncOperationWithProgress<Microsoft.Management.Deployment.InstallResult, Microsoft.Management.Deployment.InstallProgress> AsyncOperation; + Double Progress; + String StatusText; + Windows.UI.Core.CoreDispatcher Dispatcher; + } + + [default_interface] + runtimeclass MainPage : Windows.UI.Xaml.Controls.Page + { + MainPage(); + + Windows.Foundation.Collections.IObservableVector<Microsoft.Management.Deployment.PackageCatalogReference> PackageCatalogs{ get; }; + Windows.Foundation.Collections.IObservableVector<Microsoft.Management.Deployment.CatalogPackage> InstalledPackages{ get; }; + Windows.Foundation.Collections.IObservableVector<ActivePackageView> ActivePackages{ get; }; + } + + declare + { + interface Windows.Foundation.Collections.IVector<ActivePackageView>; + interface Windows.Foundation.Collections.IVectorView<ActivePackageView>; + } +} diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.xaml b/samples/WinGetUWPCaller/WinGetUWPCaller/MainPage.xaml @@ -0,0 +1,117 @@ +<!-- Copyright (c) Microsoft Corporation. + Licensed under the MIT License. --> +<Page + x:Class="WinGetUWPCaller.MainPage" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="using:WinGetUWPCaller" + xmlns:deployment="using:Microsoft.Management.Deployment" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d"> + + <Page.Resources> + <ResourceDictionary> + <Style TargetType="StackPanel"> + <Setter Property="Margin" Value="5" /> + <Setter Property="HorizontalAlignment" Value="Center" /> + </Style> + <Style TargetType="Button"> + <Setter Property="Margin" Value="5" /> + <Setter Property="HorizontalAlignment" Value="Center" /> + </Style> + </ResourceDictionary> + </Page.Resources> + + <Grid MinWidth="800" MinHeight="600"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + + <StackPanel Grid.Row="1"> + <TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Select Catalog(s)</TextBlock> + + <Button x:Name="loadCatalogsButton" Click="LoadCatalogsButtonClickHandler">Load Catalogs</Button> + <TextBlock x:Name="catalogStatusText" Text="" HorizontalAlignment="Center" Margin="0,0,0,20"/> + <TextBlock>Select catalog(s) to use</TextBlock> + <ListBox x:Name="catalogsListBox" ItemsSource="{x:Bind PackageCatalogs}" SelectionChanged="CatalogSelectionChangedHandler" SelectionMode="Multiple" Height="200"> + <ItemsControl.ItemTemplate> + <DataTemplate x:DataType="deployment:PackageCatalogReference"> + <TextBlock Text="{x:Bind Info.Name, Mode=OneTime}"/> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ListBox> + </StackPanel> + + <StackPanel Grid.Row="1" Grid.Column="1"> + <TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Package Operations</TextBlock> + <TextBlock>Search for a package from the selected catalog(s) and take action on it.</TextBlock> + + <StackPanel Orientation="Horizontal"> + <TextBox x:Name="queryTextBox" Header="Find a package:" PlaceholderText="Query (e.g. Microsoft.Teams)"></TextBox> + <ComboBox x:Name="searchField" Header="Search options" Margin="5,0,5,0" SelectedIndex="0"> + <ComboBoxItem Content="Generic query"></ComboBoxItem> + <ComboBoxItem Content="Identifier (case-insensitive)"></ComboBoxItem> + <ComboBoxItem Content="Name (substring)"></ComboBoxItem> + </ComboBox> + <Button x:Name="searchButton" Click="SearchButtonClickHandler" VerticalAlignment="Bottom" Margin="5,0,5,0">🔍</Button> + </StackPanel> + + <StackPanel Orientation="Horizontal"> + <Button x:Name="installButton" Click="InstallButtonClickHandler" IsEnabled="False">Install</Button> + <Button x:Name="upgradeButton" Click="UpgradeButtonClickHandler" IsEnabled="False">Upgrade</Button> + <Button x:Name="downloadButton" Click="DownloadButtonClickHandler" IsEnabled="False">Download</Button> + <Button x:Name="cancelButton" Click="CancelButtonClickHandler" IsEnabled="False">Cancel</Button> + </StackPanel> + + <ProgressBar x:Name="operationProgressBar" Value="0" Maximum="100" Width="350"/> + <TextBlock x:Name="operationStatusText" Text="" HorizontalAlignment="Center" Margin="0,0,0,20"/> + + <TextBox x:Name="downloadDirectoryTextBox" Header="Download Location:" PlaceholderText="Existing directory path to download to"></TextBox> + </StackPanel> + + <StackPanel Grid.Row="2" Margin="3"> + <TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Installed Packages</TextBlock> + <TextBlock>View installed package information</TextBlock> + <Button x:Name="refreshInstalledButton" Click="RefreshInstalledButtonClickHandler" IsEnabled="True">Refresh</Button> + <TextBlock x:Name="installedStatusText" Text=""/> + <ListBox x:Name="installedListBox" ItemsSource="{x:Bind InstalledPackages}" Height="300" SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Visible"> + <ItemsControl.ItemTemplate> + <DataTemplate x:DataType="deployment:CatalogPackage"> + <TextBlock Text="{x:Bind Name, Mode=OneTime}"/> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ListBox> + + <Button x:Name="uninstallButton" Click="UninstallButtonClickHandler" IsEnabled="True" Margin="5,20,5,5">Uninstall</Button> + <ProgressBar x:Name="uninstallProgressBar" Value="0" Maximum="100" Width="350"/> + <TextBlock x:Name="uninstallStatusText" Text="" HorizontalAlignment="Center" Margin="0,0,0,20"/> + </StackPanel> + + <StackPanel Grid.Row="2" Grid.Column="1" Margin="3"> + <TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Active Operations</TextBlock> + <TextBlock>View active package install/upgrade operations</TextBlock> + <StackPanel Orientation="Horizontal" > + <Button x:Name="activeRefreshButton" Click="RefreshActiveButtonClickHandler" IsEnabled="True">Refresh</Button> + </StackPanel> + <TextBlock x:Name="activeStatusText" Text=""/> + <ListBox x:Name="activeListBox" ItemsSource="{x:Bind ActivePackages}" Height="300" ScrollViewer.VerticalScrollBarVisibility="Visible"> + <ItemsControl.ItemTemplate> + <DataTemplate x:DataType="local:ActivePackageView"> + <StackPanel HorizontalAlignment="Center"> + <TextBlock Text="{x:Bind Package.Id, Mode=OneWay}"/> + <ProgressBar Value="{x:Bind Progress, Mode=OneWay}" Maximum="100" Width="200px"></ProgressBar> + <TextBlock Text="{x:Bind StatusText, Mode=OneWay}" HorizontalAlignment="Center"></TextBlock> + </StackPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ListBox> + </StackPanel> + </Grid> +</Page> diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/Package.appxmanifest b/samples/WinGetUWPCaller/WinGetUWPCaller/Package.appxmanifest @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" + xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" + xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" + xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" + IgnorableNamespaces="uap mp rescap"> + <Identity Name="SampleWinGetCaller" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" /> + <mp:PhoneIdentity PhoneProductId="8b5526fe-0870-42b7-bde0-da8c4c7ea1aa" PhonePublisherId="00000000-0000-0000-0000-000000000000" /> + <Properties> + <DisplayName>Sample WinGet Caller</DisplayName> + <PublisherDisplayName>Microsoft Corporation</PublisherDisplayName> + <Logo>Assets\StoreLogo.png</Logo> + </Properties> + <Dependencies> + <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" /> + </Dependencies> + <Resources> + <Resource Language="x-generate" /> + </Resources> + <Applications> + <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="Sample WinGet Caller"> + <uap:VisualElements DisplayName="SampleWinGetCaller" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" BackgroundColor="transparent" Description="Sample WinGet UWP caller"> + <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"></uap:DefaultTile> + </uap:VisualElements> + </Application> + </Applications> + <Capabilities> + <Capability Name="internetClient" /> + <rescap:Capability Name="packageManagement" /> + </Capabilities> +</Package>+ \ No newline at end of file diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/WinGetUWPCaller.vcxproj b/samples/WinGetUWPCaller/WinGetUWPCaller/WinGetUWPCaller.vcxproj @@ -0,0 +1,204 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.props')" /> + <PropertyGroup Label="Globals"> + <CppWinRTOptimized>true</CppWinRTOptimized> + <CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge> + <CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata> + <MinimalCoreWin>true</MinimalCoreWin> + <ProjectGuid>{37f1fd2a-4d63-45a0-82aa-66ef126cb322}</ProjectGuid> + <ProjectName>WinGetUWPCaller</ProjectName> + <RootNamespace>WinGetUWPCaller</RootNamespace> + <DefaultLanguage>en-US</DefaultLanguage> + <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion> + <AppContainerApplication>true</AppContainerApplication> + <ApplicationType>Windows Store</ApplicationType> + <ApplicationTypeRevision>10.0</ApplicationTypeRevision> + <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.22000.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '17.0'">v143</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <UseDebugLibraries>true</UseDebugLibraries> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros"> + <GenerateAppInstallerFile>False</GenerateAppInstallerFile> + <AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm> + <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision> + <GenerateTestArtifacts>True</GenerateTestArtifacts> + <AppxBundlePlatforms>x64</AppxBundlePlatforms> + <HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks> + <AppxBundle>Always</AppxBundle> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <WarningLevel>Level4</WarningLevel> + <AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions> + <!--Temporarily disable cppwinrt heap enforcement to work around xaml compiler generated std::shared_ptr use --> + <AdditionalOptions Condition="'$(CppWinRTHeapEnforcement)'==''">/DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)</AdditionalOptions> + <DisableSpecificWarnings> + </DisableSpecificWarnings> + <PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'"> + <ClCompile> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <PostBuildEvent> + <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + </Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> + <ClCompile> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + <PostBuildEvent> + <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + </Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="ActivePackageView.h" /> + <ClInclude Include="pch.h" /> + <ClInclude Include="App.h"> + <DependentUpon>App.xaml</DependentUpon> + </ClInclude> + <ClInclude Include="MainPage.h"> + <DependentUpon>MainPage.xaml</DependentUpon> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ApplicationDefinition Include="App.xaml"> + <SubType>Designer</SubType> + </ApplicationDefinition> + <Page Include="MainPage.xaml"> + <SubType>Designer</SubType> + </Page> + </ItemGroup> + <ItemGroup> + <AppxManifest Include="Package.appxmanifest"> + <SubType>Designer</SubType> + </AppxManifest> + </ItemGroup> + <ItemGroup> + <Image Include="Assets\LockScreenLogo.scale-200.png" /> + <Image Include="Assets\SplashScreen.scale-200.png" /> + <Image Include="Assets\Square150x150Logo.scale-200.png" /> + <Image Include="Assets\Square44x44Logo.scale-200.png" /> + <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" /> + <Image Include="Assets\StoreLogo.png" /> + <Image Include="Assets\Wide310x150Logo.scale-200.png" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="ActivePackageView.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader>Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="App.cpp"> + <DependentUpon>App.xaml</DependentUpon> + </ClCompile> + <ClCompile Include="MainPage.cpp"> + <DependentUpon>MainPage.xaml</DependentUpon> + </ClCompile> + <ClCompile Include="$(GeneratedFilesDir)module.g.cpp" /> + </ItemGroup> + <ItemGroup> + <Midl Include="App.idl"> + <DependentUpon>App.xaml</DependentUpon> + </Midl> + <Midl Include="MainPage.idl"> + <DependentUpon>MainPage.xaml</DependentUpon> + </Midl> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> + <Target Name="_AddCustomPackagePayload" AfterTargets="_ComputeAppxPackagePayload"> + <PropertyGroup> + <NugetRuntimeID Condition="'$(Platform)'=='Win32'">win10-x86</NugetRuntimeID> + <NugetRuntimeID Condition="'$(Platform)'=='x64'">win10-x64</NugetRuntimeID> + <NugetRuntimeID Condition="'$(Platform)'=='ARM64'">win10-arm64</NugetRuntimeID> + </PropertyGroup> + <ItemGroup> + <AppxPackagePayload Include="$(SolutionDir)packages\Microsoft.WindowsPackageManager.ComInterop.1.8.1911\runtimes\$(NugetRuntimeID)\native\Microsoft.Management.Deployment.Dynamic.dll"> + <TargetPath>Microsoft.Management.Deployment.dll</TargetPath> + </AppxPackagePayload> + </ItemGroup> + </Target> + <ItemGroup> + <Reference Include="Microsoft.Management.Deployment"> + <HintPath>..\packages\Microsoft.WindowsPackageManager.ComInterop.1.8.1911\lib\Microsoft.Management.Deployment.winmd</HintPath> + <IsWinMDFile>true</IsWinMDFile> + <Implementation>Microsoft.Management.Deployment.dll</Implementation> + </Reference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + <Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.targets')" /> + </ImportGroup> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.props'))" /> + <Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.210503.1\build\native\Microsoft.Windows.CppWinRT.targets'))" /> + </Target> +</Project>+ \ No newline at end of file diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/WinGetUWPCaller.vcxproj.filters b/samples/WinGetUWPCaller/WinGetUWPCaller/WinGetUWPCaller.vcxproj.filters @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ApplicationDefinition Include="App.xaml" /> + </ItemGroup> + <ItemGroup> + <Page Include="MainPage.xaml" /> + </ItemGroup> + <ItemGroup> + <Midl Include="App.idl" /> + <Midl Include="MainPage.idl" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pch.cpp" /> + <ClCompile Include="App.cpp" /> + <ClCompile Include="MainPage.cpp" /> + <ClCompile Include="$(GeneratedFilesDir)module.g.cpp" /> + <ClCompile Include="InstallingPackageView.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="pch.h" /> + <ClInclude Include="InstallingPackageView.h" /> + </ItemGroup> + <ItemGroup> + <Image Include="Assets\Wide310x150Logo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\SplashScreen.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\Square44x44Logo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\Square150x150Logo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\StoreLogo.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\LockScreenLogo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + </ItemGroup> + <ItemGroup> + <AppxManifest Include="Package.appxmanifest" /> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <Filter Include="Assets"> + <UniqueIdentifier>{adeebf4e-70b7-41ae-936b-ded00e6e6777}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project>+ \ No newline at end of file diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/packages.config b/samples/WinGetUWPCaller/WinGetUWPCaller/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Microsoft.Windows.CppWinRT" version="2.0.210503.1" targetFramework="native" /> + <package id="Microsoft.WindowsPackageManager.ComInterop" version="1.8.1911" targetFramework="native" /> +</packages>+ \ No newline at end of file diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/pch.cpp b/samples/WinGetUWPCaller/WinGetUWPCaller/pch.cpp @@ -0,0 +1,3 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" diff --git a/samples/WinGetUWPCaller/WinGetUWPCaller/pch.h b/samples/WinGetUWPCaller/WinGetUWPCaller/pch.h @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include <windows.h> +#include <unknwn.h> +#include <hstring.h> +#include <winrt/Windows.Foundation.h> +#include <winrt/Windows.Foundation.Collections.h> +#include <winrt/Windows.ApplicationModel.Activation.h> +#include <winrt/Windows.UI.Core.h> +#include <winrt/Windows.UI.Xaml.h> +#include <winrt/Windows.UI.Xaml.Controls.h> +#include <winrt/Windows.UI.Xaml.Controls.Primitives.h> +#include <winrt/Windows.UI.Xaml.Data.h> +#include <winrt/Windows.UI.Xaml.Interop.h> +#include <winrt/Windows.UI.Xaml.Markup.h> +#include <winrt/Windows.UI.Xaml.Navigation.h> + +#include <initializer_list> +#include <iomanip> +#include <mutex> +#include <sstream> +#include <string> +#include <string_view> +#include <vector>