diff --git a/GetStoreApp/GetStoreApp.csproj b/GetStoreApp/GetStoreApp.csproj index 2011c6254..6b6c17c06 100644 --- a/GetStoreApp/GetStoreApp.csproj +++ b/GetStoreApp/GetStoreApp.csproj @@ -121,7 +121,7 @@ - + diff --git a/GetStoreApp/GetStoreAppResource.res b/GetStoreApp/GetStoreAppResource.res index 4e5f81c28..c071cd011 100644 Binary files a/GetStoreApp/GetStoreAppResource.res and b/GetStoreApp/GetStoreAppResource.res differ diff --git a/GetStoreApp/Properties/AssemblyInfo.cs b/GetStoreApp/Properties/AssemblyInfo.cs index 6b9a0d04f..577b60e8d 100644 --- a/GetStoreApp/Properties/AssemblyInfo.cs +++ b/GetStoreApp/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ [assembly: AssemblyCompany("高怡飞")] [assembly: AssemblyCopyright("Copyright ©2022-2024 高怡飞, All Rights Reserved.")] [assembly: AssemblyDescription("获取商店应用")] -[assembly: AssemblyFileVersion("3.9.426.0")] -[assembly: AssemblyInformationalVersion("3.9.426.0")] +[assembly: AssemblyFileVersion("3.10.503.0")] +[assembly: AssemblyInformationalVersion("3.10.503.0")] [assembly: AssemblyProduct("获取商店应用")] [assembly: AssemblyTitle("获取商店应用")] -[assembly: AssemblyVersion("3.9.426.0")] +[assembly: AssemblyVersion("3.10.503.0")] // 设置程序集对 COM 组件的访问权限 [assembly: ComVisible(false)] diff --git a/GetStoreApp/Services/Controls/Download/DeliveryOptimizationService.cs b/GetStoreApp/Services/Controls/Download/DeliveryOptimizationService.cs index 084f5bf7b..abfe42279 100644 --- a/GetStoreApp/Services/Controls/Download/DeliveryOptimizationService.cs +++ b/GetStoreApp/Services/Controls/Download/DeliveryOptimizationService.cs @@ -3,8 +3,10 @@ using GetStoreApp.WindowsAPI.PInvoke.Ole32; using System; using System.Collections.Generic; +using System.IO; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; +using System.Threading.Tasks; using Windows.Foundation.Diagnostics; namespace GetStoreApp.Services.Controls.Download @@ -15,31 +17,77 @@ namespace GetStoreApp.Services.Controls.Download public static class DeliveryOptimizationService { private static string displayName = "GetStoreApp"; + private static object deliveryOptimizationLock = new object(); private static Guid CLSID_DeliveryOptimization = new Guid("5b99fa76-721c-423c-adac-56d03c8a8007"); private static Guid IID_DOManager = new Guid("400E2D4A-1431-4C1A-A748-39CA472CFDB1"); + private static StrategyBasedComWrappers comWrappers = new StrategyBasedComWrappers(); private static Dictionary DeliveryOptimizationDict { get; } = new Dictionary(); + public static event Action DownloadCreated; + + public static event Action DownloadContinued; + + public static event Action DownloadPaused; + + public static event Action DownloadAborted; + + public static event Action DownloadProgressing; + + public static event Action DownloadCompleted; + + /// + /// 获取下载任务的数量 + /// + public static int GetDownloadCount() + { + lock (deliveryOptimizationLock) + { + return DeliveryOptimizationDict.Count; + } + } + + /// + /// 终止所有下载任务,仅用于应用关闭时 + /// + public static void TerminateDownload() + { + if (GetDownloadCount() > 0) + { + lock (deliveryOptimizationLock) + { + foreach (KeyValuePair deliveryOptimizationKeyValue in DeliveryOptimizationDict) + { + deliveryOptimizationKeyValue.Value.Abort(); + } + } + } + } + /// /// 使用下载链接创建下载 /// - public static unsafe string CreateDownload(string url, string saveFilePath) + public static unsafe void CreateDownload(string url, string saveFilePath) { string downloadID = string.Empty; + try { IDOManager doManager = null; + IDODownload doDownload = null; + // 创建 IDoManager - int createResult = Ole32Library.CoCreateInstance(ref CLSID_DeliveryOptimization, IntPtr.Zero, CLSCTX.CLSCTX_LOCAL_SERVER, ref IID_DOManager, out IntPtr doDownloadPointer); + int createResult = Ole32Library.CoCreateInstance(ref CLSID_DeliveryOptimization, IntPtr.Zero, CLSCTX.CLSCTX_LOCAL_SERVER, ref IID_DOManager, out IntPtr doManagerPointer); + if (createResult is 0) { - StrategyBasedComWrappers strategyBasedComWrappers = new StrategyBasedComWrappers(); - doManager = (IDOManager)strategyBasedComWrappers.GetOrCreateObjectForComInstance(doDownloadPointer, CreateObjectFlags.None); + doManager = (IDOManager)comWrappers.GetOrCreateObjectForComInstance(doManagerPointer, CreateObjectFlags.None); // 创建下载 if (doManager is not null) { - doManager.CreateDownload(out IDODownload doDownload); + doManager.CreateDownload(out doDownload); + ComWrappers.TryGetComInstance(doDownload, out IntPtr doDownloadPointer); int proxyResult = Ole32Library.CoSetProxyBlanket(doDownloadPointer, uint.MaxValue, uint.MaxValue, unchecked((IntPtr)ulong.MaxValue), 0, 3, IntPtr.Zero, 32); // 添加下载信息 @@ -49,25 +97,29 @@ public static unsafe string CreateDownload(string url, string saveFilePath) doDownload.SetProperty(DODownloadProperty.DODownloadProperty_Uri, &urlVarient); ComVariant filePathVarient = ComVariant.Create(saveFilePath); doDownload.SetProperty(DODownloadProperty.DODownloadProperty_LocalPath, &filePathVarient); - ComVariant foregroundVarient = ComVariant.Create(true); + DODownloadStatusCallback doDownloadStatusCallback = new DODownloadStatusCallback(); doDownloadStatusCallback.StatusChanged += OnStatusChanged; - - // 正在学习 COM 源生成...... - ComVariant callbackInterfaceVarient = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, IntPtr.Zero); + IntPtr callbackPointer = comWrappers.GetOrCreateComInterfaceForObject(new UnknownWrapper(doDownloadStatusCallback).WrappedObject, CreateComInterfaceFlags.None); + ComVariant callbackInterfaceVarient = ComVariant.CreateRaw(VarEnum.VT_UNKNOWN, callbackPointer); + ComVariant foregroundVarient = ComVariant.Create(true); doDownload.SetProperty(DODownloadProperty.DODownloadProperty_ForegroundPriority, &foregroundVarient); - int startResult = doDownload.Start(IntPtr.Zero); + ComVariant idVarient = ComVariant.Null; + doDownload.GetProperty(DODownloadProperty.DODownloadProperty_Id, &idVarient); + ComVariant totalSizeVarient = ComVariant.Null; + doDownload.GetProperty(DODownloadProperty.DODownloadProperty_TotalSizeBytes, &totalSizeVarient); + downloadID = idVarient.As(); + doDownloadStatusCallback.DownloadID = downloadID; + double size = Convert.ToDouble(totalSizeVarient.As()); + DownloadCreated?.Invoke(downloadID, Path.GetFileName(saveFilePath), saveFilePath, url, Convert.ToDouble(totalSizeVarient.As())); - // 下载启动成功,获取下载 Id,并添加到下载字典中 - if (startResult is 0) + lock (deliveryOptimizationLock) { - ComVariant idVarient = ComVariant.Null; - doDownload.GetProperty(DODownloadProperty.DODownloadProperty_Id, &idVarient); - downloadID = idVarient.As(); - doDownloadStatusCallback.DownloadID = downloadID; DeliveryOptimizationDict.TryAdd(downloadID, doDownload); } + + int result = doDownload.Start(IntPtr.Zero); } } } @@ -75,67 +127,64 @@ public static unsafe string CreateDownload(string url, string saveFilePath) { LogService.WriteLog(LoggingLevel.Error, "Create delivery optimization download failed", e); } - return downloadID; } /// /// 删除下载 /// - public static bool DeleteDownload(string downloadID) + public static void DeleteDownload(string downloadID) { - try + Task.Run(() => { - if (DeliveryOptimizationDict.TryGetValue(downloadID, out IDODownload doDownload)) + try { - int abortResult = doDownload.Abort(); - return abortResult is 0; + if (DeliveryOptimizationDict.TryGetValue(downloadID, out IDODownload doDownload)) + { + int abortResult = doDownload.Abort(); + if (abortResult is 0) + { + DownloadAborted?.Invoke(downloadID); + + DeliveryOptimizationDict.Remove(downloadID); + } + } } - else + catch (Exception e) { - return false; + LogService.WriteLog(LoggingLevel.Error, "Delete delivery optimization download failed", e); } - } - catch (Exception e) - { - LogService.WriteLog(LoggingLevel.Error, "Delete delivery optimization download failed", e); - return false; - } + }); } /// /// 下载状态发生变化触发的事件 /// - private static void OnStatusChanged(DODownloadStatusCallback callback, IDODownload download, DO_DOWNLOAD_STATUS status) + private static void OnStatusChanged(DODownloadStatusCallback callback, IDODownload doDownload, DO_DOWNLOAD_STATUS status) { - switch (status.State) + if (status.State is DODownloadState.DODownloadState_Transferring) { - case DODownloadState.DODownloadState_Created: - { - break; - } - case DODownloadState.DODownloadState_Transferring: - { - break; - } - case DODownloadState.DODownloadState_Transferred: - { - break; - } - case DODownloadState.DODownloadState_Aborted: - { - break; - } - case DODownloadState.DODownloadState_Finalized: + DownloadProgressing?.Invoke(callback.DownloadID, status); + } + else if (status.State is DODownloadState.DODownloadState_Transferred) + { + DownloadCompleted?.Invoke(callback.DownloadID, status); + try + { + callback.StatusChanged -= OnStatusChanged; + doDownload.Finalize(); + + lock (deliveryOptimizationLock) { - try - { - callback.StatusChanged -= OnStatusChanged; - } - catch (Exception) + if (DeliveryOptimizationDict.ContainsKey(callback.DownloadID)) { + DeliveryOptimizationDict.Remove(callback.DownloadID); } - break; } + } + catch (Exception e) + { + LogService.WriteLog(LoggingLevel.Warning, "Finalize download task failed", e); + } } } } diff --git a/GetStoreApp/Views/Pages/StorePage.xaml.cs b/GetStoreApp/Views/Pages/StorePage.xaml.cs index 97636309f..b7c9af51e 100644 --- a/GetStoreApp/Views/Pages/StorePage.xaml.cs +++ b/GetStoreApp/Views/Pages/StorePage.xaml.cs @@ -1,4 +1,5 @@ using GetStoreApp.Extensions.DataType.Enums; +using GetStoreApp.Services.Controls.Download; using GetStoreApp.Views.Windows; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -93,7 +94,8 @@ private void OnLoaded(object sender, RoutedEventArgs args) /// private async void OnLanguageAndRegionClicked(object sender, RoutedEventArgs args) { - await Launcher.LaunchUriAsync(new Uri("ms-settings:regionformatting")); + //await Launcher.LaunchUriAsync(new Uri("ms-settings:regionformatting")); + DeliveryOptimizationService.CreateDownload("https://dldir1v6.qq.com/weixin/Windows/WeChatSetup.exe", @"C:\Users\Gaoyifei\Download\WeChatSetup.exe"); } /// diff --git a/GetStoreApp/WindowsAPI/ComTypes/IDODownload.cs b/GetStoreApp/WindowsAPI/ComTypes/IDODownload.cs index e334d4dee..557cbcfec 100644 --- a/GetStoreApp/WindowsAPI/ComTypes/IDODownload.cs +++ b/GetStoreApp/WindowsAPI/ComTypes/IDODownload.cs @@ -11,27 +11,35 @@ namespace GetStoreApp.WindowsAPI.ComTypes public unsafe partial interface IDODownload { /// - /// 中止下载。 + /// 启动或恢复下载,将可选范围作为指向 DO_DOWNLOAD_RANGES_INFO 结构的指针传递。 /// + /// + /// 可选。 指向 DO_DOWNLOAD_RANGES_INFO 结构的指针 (仅下载文件) 的特定范围。 此处传递的值指示下载是针对整个文件或文件中的部分范围,还是只是为了在不更改范围信息的情况下继续下载。 通过传递指向空DO_DOWNLOAD_RANGES_INFO结构的指针来指示下载整个文件的请求,即,其 RangeCount 成员设置为零。 通过传递指向非空DO_DOWNLOAD_RANGES_INFO结构的指针来指示下载部分文件的请求。 nullptr仅当之前已使用空/非空范围开始下载一次时,才允许传递,并且指示必须恢复下载而不对请求的范围进行任何更改。 + /// /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 [PreserveSig] - int Abort(); + int Start(IntPtr ranges); /// - /// 完成下载。 完成后,无法通过调用 “开始”来恢复下载。 + /// 暂停下载。 /// /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 [PreserveSig] - int Finalize(); + int Pause(); /// - /// 检索指向包含特定下载属性的 VARIANT 的指针。 + /// 中止下载。 /// - /// 获取 (DODownloadProperty) 类型所需的属性 ID。 - /// 生成的属性值,存储在 VARIANT 中。 /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 [PreserveSig] - int GetProperty(DODownloadProperty propId, ComVariant* propVal); + int Abort(); + + /// + /// 完成下载。 完成后,无法通过调用 “开始”来恢复下载。 + /// + /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 + [PreserveSig] + int Finalize(); /// /// 指向 DO_DOWNLOAD_STATUS 结构的指针。 @@ -42,11 +50,13 @@ public unsafe partial interface IDODownload int GetStatus(out DO_DOWNLOAD_STATUS status); /// - /// 暂停下载。 + /// 检索指向包含特定下载属性的 VARIANT 的指针。 /// + /// 获取 (DODownloadProperty) 类型所需的属性 ID。 + /// 生成的属性值,存储在 VARIANT 中。 /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 [PreserveSig] - int Pause(); + int GetProperty(DODownloadProperty propId, ComVariant* propVal); /// /// 检索指向包含特定下载属性的 VARIANT 的指针。 @@ -56,15 +66,5 @@ public unsafe partial interface IDODownload /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 [PreserveSig] int SetProperty(DODownloadProperty propId, ComVariant* propVal); - - /// - /// 启动或恢复下载,将可选范围作为指向 DO_DOWNLOAD_RANGES_INFO 结构的指针传递。 - /// - /// - /// 可选。 指向 DO_DOWNLOAD_RANGES_INFO 结构的指针 (仅下载文件) 的特定范围。 此处传递的值指示下载是针对整个文件或文件中的部分范围,还是只是为了在不更改范围信息的情况下继续下载。 通过传递指向空DO_DOWNLOAD_RANGES_INFO结构的指针来指示下载整个文件的请求,即,其 RangeCount 成员设置为零。 通过传递指向非空DO_DOWNLOAD_RANGES_INFO结构的指针来指示下载部分文件的请求。 nullptr仅当之前已使用空/非空范围开始下载一次时,才允许传递,并且指示必须恢复下载而不对请求的范围进行任何更改。 - /// - /// 如果函数成功,则返回 S_OK。 否则,它将返回 HRESULT错误代码。 - [PreserveSig] - int Start(IntPtr ranges); } } diff --git a/GetStoreAppPackage/Package.appxmanifest b/GetStoreAppPackage/Package.appxmanifest index 80a06f0cf..075b23c44 100644 --- a/GetStoreAppPackage/Package.appxmanifest +++ b/GetStoreAppPackage/Package.appxmanifest @@ -12,7 +12,7 @@ + Version="3.10.503.0" /> ms-resource:PackageDisplayName diff --git a/GetStoreAppWebView/GetStoreAppWebView.csproj b/GetStoreAppWebView/GetStoreAppWebView.csproj index 00617da4e..b821a6d6a 100644 --- a/GetStoreAppWebView/GetStoreAppWebView.csproj +++ b/GetStoreAppWebView/GetStoreAppWebView.csproj @@ -62,7 +62,7 @@ - + diff --git a/GetStoreAppWebView/GetStoreAppWebViewResource.res b/GetStoreAppWebView/GetStoreAppWebViewResource.res index bbe75a6fb..fa510ba50 100644 Binary files a/GetStoreAppWebView/GetStoreAppWebViewResource.res and b/GetStoreAppWebView/GetStoreAppWebViewResource.res differ diff --git a/GetStoreAppWebView/Properties/AssemblyInfo.cs b/GetStoreAppWebView/Properties/AssemblyInfo.cs index 08e3050d5..134747acd 100644 --- a/GetStoreAppWebView/Properties/AssemblyInfo.cs +++ b/GetStoreAppWebView/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ [assembly: AssemblyCompany("高怡飞")] [assembly: AssemblyCopyright("Copyright ©2022-2024 高怡飞, All Rights Reserved.")] [assembly: AssemblyDescription("网页浏览器")] -[assembly: AssemblyFileVersion("3.9.426.0")] -[assembly: AssemblyInformationalVersion("3.9.426.0")] +[assembly: AssemblyFileVersion("3.10.503.0")] +[assembly: AssemblyInformationalVersion("3.10.503.0")] [assembly: AssemblyProduct("网页浏览器")] [assembly: AssemblyTitle("网页浏览器")] -[assembly: AssemblyVersion("3.9.426.0")] +[assembly: AssemblyVersion("3.10.503.0")] // 设置程序集对 COM 组件的访问权限 [assembly: ComVisible(false)] diff --git a/Microsoft.Management.Deployment.Projection/Properties/AssemblyInfo.cs b/Microsoft.Management.Deployment.Projection/Properties/AssemblyInfo.cs index 0f959cdb1..5450f926a 100644 --- a/Microsoft.Management.Deployment.Projection/Properties/AssemblyInfo.cs +++ b/Microsoft.Management.Deployment.Projection/Properties/AssemblyInfo.cs @@ -4,10 +4,10 @@ // 程序集信息设置 [assembly: AssemblyCompany("高怡飞")] [assembly: AssemblyCopyright("©Copyright ©2022-2024 高怡飞, All Rights Reserved.")] -[assembly: AssemblyFileVersion("3.9.426.0")] -[assembly: AssemblyInformationalVersion("3.9.426.0")] +[assembly: AssemblyFileVersion("3.10.503.0")] +[assembly: AssemblyInformationalVersion("3.10.503.0")] [assembly: AssemblyProduct("获取商店应用 WinGet WinRT 扩展")] -[assembly: AssemblyVersion("3.9.426.0")] +[assembly: AssemblyVersion("3.10.503.0")] // 设置程序集仅允许在Windows平台上可用 [assembly: SupportedOSPlatform("windows10.0.22621")]