Enhanced User Experience with Progress Dialog for NuGet Installations (#4388)

Enhanced user feedback by integrating IVsThreadedWaitDialog for NuGet package installation in Visual Studio template.

---------

Co-authored-by: Shashank Nayak <shasnayak@microsoft.com>
This commit is contained in:
Shashank 2024-05-06 15:49:07 -04:00 коммит произвёл GitHub
Родитель 2426e92225
Коммит 391235acd4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 38 добавлений и 24 удалений

Просмотреть файл

@ -50,7 +50,7 @@ namespace WindowsAppSDK.Cpp.Extension
{
// When initialized asynchronously, the current thread may be a background thread at this point.
// Do any initialization that requires the UI thread after switching to the UI thread.
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
}
#endregion

Просмотреть файл

@ -49,6 +49,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.3.32804.24" ExcludeAssets="runtime">

Просмотреть файл

@ -50,7 +50,7 @@ namespace WindowsAppSDK.Cs.Extension
{
// When initialized asynchronously, the current thread may be a background thread at this point.
// Do any initialization that requires the UI thread after switching to the UI thread.
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
}
#endregion

Просмотреть файл

@ -1,4 +1,4 @@
<Project ToolsVersion="Current">
<Project ToolsVersion="Current">
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
@ -73,6 +73,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(ItemTemplatesDir)Desktop\CSharp\BlankWindow\WinUI.Desktop.Cs.BlankWindow.csproj">

Просмотреть файл

@ -10,7 +10,6 @@ using Microsoft.VisualStudio.Threading;
using NuGet.VisualStudio;
using System;
using System.Collections.Generic;
using System.Deployment.Internal;
using System.Linq;
using System.Threading.Tasks;
@ -24,11 +23,13 @@ namespace WindowsAppSDK.TemplateUtilities
private IComponentModel _componentModel;
private IEnumerable<string> _nuGetPackages;
private IVsNuGetProjectUpdateEvents _nugetProjectUpdateEvents;
private IVsThreadedWaitDialog2 _waitDialog;
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
ThreadHelper.ThrowIfNotOnUIThread();
_componentModel = (IComponentModel)ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel));
_waitDialog = ServiceProvider.GlobalProvider.GetService(typeof(SVsThreadedWaitDialog)) as IVsThreadedWaitDialog2;
if (_componentModel != null)
{
_nugetProjectUpdateEvents = _componentModel.GetService<IVsNuGetProjectUpdateEvents>();
@ -61,48 +62,58 @@ namespace WindowsAppSDK.TemplateUtilities
}
}
}
private async Task InstallNuGetPackageAsync(IVsPackageInstaller installer, string packageId)
private async Task InstallNuGetPackagesAsync()
{
await Task.Run(() =>
await ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
{
try
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
int canceled; // This variable will store the status after the dialog is closed
// Start the package installation task but do not await it here
var installationTask = StartInstallationAsync();
// Start the threaded wait dialog
_waitDialog.StartWaitDialog(null, "Installing NuGet packages into project...", null, null, "Operation in progress...", 0, false, true);
// Now await the installation task to complete
await installationTask;
// Once the installation is complete, end the wait dialog
_waitDialog.EndWaitDialog(out canceled);
// Check if the process was canceled before proceeding
if (canceled == 0) // If not canceled, finalize the process
{
installer.InstallPackage(null, _project, packageId, "", false);
// If there's any CPU-bound work, it will be done on the background thread.
}
catch (Exception ex)
{
LogError($"Error installing package {packageId}: {ex.Message}");
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
SaveAllProjects();
}
});
}
// InstallNuGetPackagesAsync iterates over the package list and installs each
private async Task InstallNuGetPackagesAsync()
private async Task StartInstallationAsync()
{
IVsPackageInstaller installer = _componentModel.GetService<IVsPackageInstaller>();
if (installer == null)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
LogError("Could not obtain IVsPackageInstaller service.");
return;
}
//await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
// Process each package installation
foreach (var packageId in _nuGetPackages)
{
try
{
// No version specified; it installs the latest stable version
await InstallNuGetPackageAsync(installer, packageId);
await Task.Run(() => installer.InstallPackage(null, _project, packageId, "", false));
}
catch (Exception ex)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
LogError($"Failed to install NuGet package: {packageId}. Error: {ex.Message}");
}
}
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
SaveAllProjects();
}
public void BeforeOpeningFile(ProjectItem _)
{
}

Просмотреть файл

@ -219,6 +219,7 @@ Global
{E54D1AD4-E935-479D-8A69-FC073E4DB33D} = {1A8A7481-2108-496B-802D-39F9C08D86F3}
{45777B9F-9CC1-47D7-BD66-C3C194277902} = {EC44EE95-8EC9-4EE5-A8A6-E6BE2F32C843}
{DFA6B905-57A3-4B31-A74B-25BA2243389F} = {1A8A7481-2108-496B-802D-39F9C08D86F3}
{96699B60-67B5-4186-9FEC-3963ED811FF0} = {50DEEF87-BC2F-4B45-B97D-B83135F12786}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A417E325-71BD-4C29-94F8-F21FB3F5C392}