在上一篇《迁移桌面程序到MS Store(7)——APPX + Service》中,我们提到将desktop application拆分成UI Client+Service两部分。其中UI Client可以通过Desktop Bridge技术Pacakage成APPX,上传到MS Store以供下载,而Service则仍以传统的desktop application安装包形式提供。这样势必造成用户安装时的割裂感。本篇将就这个问题进行一些讨论。

首先我们参照上图的架构创建Sample Solution,其中包括充当UI的WPFClient,升级到.NET Standard的DownloadLib,以及打包用的UWPClientPackaging工程(请先暂时忽略UWPClient工程)。

WPFClient只是一个空的Window,仅仅在Window Load的时候,询问用户是否下载文件。

        private async void MainWindow_Loaded(object sender, RoutedEventArgs e){txtLog.AppendText($"Ask user to download file.\n");var result = MessageBox.Show("We need to download file.", "Download", MessageBoxButton.YesNo);if (result == MessageBoxResult.Yes){txtLog.AppendText($"Start downloading.\n");this.progressBar.Visibility = Visibility.Visible;var downloader = new SimpleDownloader();var stream = await downloader.RequestHttpContentAsync(ConfigurationManager.AppSettings["uri"],ConfigurationManager.AppSettings["username"],ConfigurationManager.AppSettings["password"]);this.progressBar.Visibility = Visibility.Collapsed;txtLog.AppendText($"Done.\n");var path = SaveFile(stream);txtLog.AppendText($"File path is {path}.\n");Process.Start(path);txtLog.AppendText($"Start process {path}.\n");}}

这里需要注意的是,代码中的uri,username和password均写在配置文件App.config中,调试时记得填写真实的值。

  <appSettings><add key="uri" value=""/><add key="username" value=""/><add key="password" value=""/></appSettings>

DownloadLib工程在这个例子中充当了Class Library的角色,考虑到会被WPFClient和UWPClient同时调用,DownloadLib的项目类型是.NET Standard。该工程的代码也很简单,通过传入的uri,username和password进行http请求下载文件,以Stream的形式返回结果。

        public async Task<Stream> RequestHttpContentAsync(string uriString, string userName, string password){using (HttpClient client = new HttpClient()){client.BaseAddress = new Uri(uriString);client.DefaultRequestHeaders.Accept.Clear();var authorization = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes($"{userName}:{password}"));client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorization);client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));HttpResponseMessage response = await client.GetAsync(uriString);if (response.IsSuccessStatusCode){HttpContent content = response.Content;var contentStream = await content.ReadAsStreamAsync();return contentStream;}else{throw new FileNotFoundException();}}}

假设我们这里下载的文件是一个.msi的安装文件,这个安装文件即是架构图中Service部分的安装包。在完成下载后,在WPFClient中将Stream保存成文件,然后通过Process.Start(path);运行,接下来就是.msi文件的安装流程了。在安装结束后,整个application就可以正常使用了。

        private string SaveFile(Stream stream){var filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "installFile.msi");using (var fileStream = new FileStream(filePath, FileMode.Create)){byte[] buffer = new byte[2048];int bytesRead;do{bytesRead = stream.Read(buffer, 0, 2048);fileStream.Write(buffer, 0, bytesRead);} while (bytesRead > 0);}return filePath;}

WPFClient最终是通过UWPClientPackaging工程打包成为APPX,实际对File和Process的操作都是标准的WPF代码。不存在权限的问题。当然如果当前用户没有admin权限,不被允许安装任何软件,这就超出了我们讨论的范围。
接下来我们来看纯UWPClient的情况。UWPClient工程同样添加了对DownloadLib的引用,界面也基本一致。稍有不同之处在于不能使用System.IO.File对象,而是要通过StorageFolder来保存文件。同样也不能够使用Process.Start()方法,而是通过Launcher对象来打开保存文件所在的文件夹。某软出于安全角度,不允许Launcher对象运行exe,msi等类型的可执行文件。所以只能打开文件夹让用户手动点击安装。
https://docs.microsoft.com/en-us/uwp/api/windows.system.launcher.launchfileasync
This API also imposes several restrictions on what types of files it can launch. Many file types that contain executable code, for example .exe, .msi, and .js files, are blocked from launching. This restriction protects users from potentially malicious files that could modify the system.

        private async void MainPage_Loaded(object sender, RoutedEventArgs e){txtLog.Text += $"Ask user to download file.\n";var dialog = new MessageDialog("Do you want to download installation file?");dialog.Commands.Add(new UICommand { Label = "Ok", Id = 0 });dialog.Commands.Add(new UICommand { Label = "Cancel", Id = 1 });var res = await dialog.ShowAsync();if ((int)res.Id == 0){txtLog.Text += $"Start downloading.\n";this.progressRing.IsActive = true;var downloader = new SimpleDownloader();var stream = await downloader.RequestHttpContentAsync("","","");this.progressRing.IsActive = false;var file = await SaveStorageFile(stream);var result = await Launcher.LaunchFolderAsync(ApplicationData.Current.LocalFolder);txtLog.Text += $"Done.\n ";}}

本篇讨论了如何在APPX中下载文件并运行,使用户仅需要在MS Store中进行一次下载即可完成整个application的安装。实际使用中更适合通过Desktop Bridge打包的desktop application。而对纯UWP的客户端并不友好。对纯UWP客户端的处理我们在下一篇中做更进一步讨论。
GitHub:
https://github.com/manupstairs/AppxDownloadWin32Component

转载于:https://www.cnblogs.com/manupstairs/p/10918862.html

迁移桌面程序到MS Store(8)——通过APPX下载Win32Component相关推荐

  1. Vue项目打包成桌面程序exe除了使用electron-vue你还可以这样

    场景 electron-vue 基于 vue (基本上是它听起来的样子) 来构造 electron 应用程序的样板代码. 该项目的目的,是为了要避免使用 vue 手动建立起 electron 应用程序 ...

  2. electron 桌面程序_如何使用Electron使用JavaScript构建您的第一个桌面应用程序

    electron 桌面程序 by Carol-Theodor Pelu 通过Carol-Theodor Pelu 如何使用Electron使用JavaScript构建您的第一个桌面应用程序 (How ...

  3. [转载] flutter开发桌面程序_在开始使用Flutter开发应用程序之前要了解的5条提示

    参考链接: Python中的桌面通知程序 flutter开发桌面程序 1.始终取消您的流订阅: (1. Always cancel your stream subscription:) When I ...

  4. Electron前端开发桌面程序--入门篇

    前言 前端开发桌面程序这个概念已经出现有一段时间了,这项技术也已经走向成熟,Github上nw和光electron的star就差不多有10w颗星了,github也衍生出了很多开源的桌面项目俨然成了一个 ...

  5. 桌面安装计算机,获取新计算机或重新安装Windows后快速安装桌面程序的4种方法 | MOS86...

    Windows桌面是没有应用程序商店式软件安装过程的唯一平台.智能手机,平板电脑,Mac和Linux PC都可以快速安装多个程序 安装你最喜欢的节目没有我们 使用Ninite安装多个程序 Ninite ...

  6. pyqt designer connect无响应_如何用PyQt编写桌面程序,创建并打开播放列表?

    由于电脑上的短视频太多了,并且分别存放在各个子目录下,每次更新后想要整理视频比较麻烦,因此想用Python编写程序来辅助管理视频文件.其实写个Python脚本程序即可实现大器的需求,但为了多练习PyQ ...

  7. Nativefier 网页转桌面程序 app

    Nativefier 网页转桌面程序 Nativefier简介 Nativefier是一个命令行工具,仅仅通过一行代码就可以轻松地为任何的网站创建桌面应用程序,应用程序通过Electron打包成系统可 ...

  8. 桌面程序调用Web Service应用实例

    作者:朱金灿 来源:blog.csdn.net/clever101 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com ...

  9. SharpUpdater:开源的.NET桌面程序自动更新组件

    SharpUpdater开源了! http://sharpupdater.codeplex.com/ 简  介 SharpUpdater是一个开源的.NET Windows桌面程序自动更新的组件.它提 ...

最新文章

  1. 滴滴裁员补偿丰厚,员工称裁出幸福感?
  2. Java中的HashCode(2)之Hashset造成的内存泄露
  3. 2022-03-31 一些后续
  4. Eureka出现No instances available for xxx的五种解决方案(不能解决你骂我)
  5. python中字典和集合对象是无序的_Python基础(四):元组、字典和集合
  6. expect巡检服务器_Shell-批量巡检服务器脚本
  7. python 简历_用Python翻译我的简历
  8. flash as3笔记1
  9. Winboard - X
  10. A better zip bomb,比例28000000:1「V2」
  11. linux查看网口位置命令,Linux下查看网卡信息及确定网卡位置
  12. 300字总结计算机flash,flash实训报告心得(共10篇).docx
  13. 微信公众号编辑器图片上传后有白色背景
  14. eclipse 提示destination folder must be accessible
  15. Leslie--Chueng项目服务端、小程序的本地部署操作教程
  16. 论文数据分析-1(论文数据统计)
  17. ZAC深度解析:区块链技术如何重塑汽车后市场?
  18. 从傅里叶变换到Laplace变换
  19. docker实现MySQL主主互备(主主双机热备)
  20. Unity 材质替换工具说明

热门文章

  1. python中静态方法存在的意义
  2. python作用域——LEGB规则
  3. 解释一下全连接层CNN中全连接层是什么样的
  4. 漫步最优化十二——局部极小与极大的充分必要条件(下)
  5. 2.12 主成分分析(下)
  6. python存储数据丢失的存储器是_数据缺失值的4种处理方法
  7. 最佳的MongoDB客户端管理工具
  8. C 免费窗体控件Krypton Toolkit 4 2 0的使用
  9. 机器学习笔记I: 基于逻辑回归的分类预测
  10. python标准库使用教程_Python标准库概览