本篇我们以一个Sample工程,来说明如何把一个常见结构的desktop application,转制成APPX并在MS Store提供下载。

之前的篇章中,我们已经介绍了一些内容,包括如何通过Visual Studio创建Packaging工程, 如何将Class Libraries转换到.NET Standard版本。至此,UI界面,以及部分DLL的迁移问题得到解决。但有时候我们的desktop application还包括一个本地的Background Service。那么目前微软推荐的策略,依然是通过创建一个WCF服务,然后host在Windows Service上,来提供给前端的APPX访问。

可能有同学要问,为什么我们需要Windows Service。这是因为在前台程序中,一般不会要求admin权限,这在企业级软件中是较为常见的需求,用PowerPiont的普通员工,通常被认为即没有power也没有point,更不需要admin权限……(悲剧啊T_T)但我们可以把需要admin权限,访问硬件等相关操作,放到Service中,由IT统一部署到机器上,避免了没有admin权限无法正常运行程序的问题。

在接下来的Sample中,我们试图通过代码启动一个Windows服务"aspnet_state"。这个工程非常的简单,我们要做的仅仅是在UWP project中调用一下Windonws Service上运行的WCF服务。工程结构如下图。因为工程主要想说明UI程序对WCF服务的引用,所以请不要在意使用UI程序是UWP还是WPF。实际使用中,对于Desktop Bridge的程序,非WCF的其他Background Service也是可以的,比如Named Pipes等。

我们的UI部分非常的简单,仅是在MainPage.cs中调用WCF服务中提供的方法,这里我们可以看到传递了一个string类型的参数作为要启动的service name。

    public sealed partial class MainPage : Page
{
private string serviceName = "aspnet_state";
private LocalServiceClient client = new LocalServiceClient(); public MainPage()
{
this.InitializeComponent();
} private async void Button_Click(object sender, RoutedEventArgs e)
{
var status = await client.StartServiceAsync(serviceName);
textBlockStatus.Text = status.ToString();
}
}

如何编写WCF服务这里就不赘述了,有兴趣的同学可以去MSDN上学习:
https://docs.microsoft.com/en-us/dotnet/framework/wcf/index
同样直接给出如何将WCF服务host在Windows Service上的链接:
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-host-a-wcf-service-in-a-managed-windows-service
在WCF service的代码里,我们通过ServiceController启动另一个系统的Windows Service,需要注意的是,我们测试用的"aspnet_state"默认是未开启的,而启动Windows Service要求程序具有admin权限。

    public class LocalServiceWrapper : ILocalService
{
public ServiceControllerStatus StartService(string name)
{
ServiceController controller = new ServiceController(name); if (controller.Status == ServiceControllerStatus.Stopped)
{
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds());
}
return controller.Status;
}
}

你也可以试试Bluetooth Support Service,Service name是"bthserv"。通过程序开启蓝牙服务似乎更合理,但反复测试disable/enable蓝牙让我很烦躁。所以最终我换成了"aspnet_state"。
把程序拆分成UI和WCF Service两部分的目的,是将需要admin权限等不符合MS Store审核要求的代码,从APPX中移出,已servcie的形式来调用。最终的结构图可以分为两种。
第一种是采用Desktop Bridge的形式,APPX部分可以继续包含native C++ libraries,也可以调用任何形式的background service。唯一的问题是,在提交APPX到商店审核的时候,需要申请相应权限。企业级的软件通过审核的可能性很大,个人作品就不清楚了。审核通过后APPX获得微软的签名。此时用户可从商店下载APPX,然后手动安装Service部分。也可以由公司IT以Sideload的方式统一安装APPX+Service。

第二种更为纯粹,由UWP+.NET Standard+WCF组成,相应也需要更多的改动,而Native C++ Libraries的部分则需要下沉到Service中。这种的好处在于迁移的更为彻底,对未来有着更好的适应。当然哪天某软翻脸不认账,抛弃UWP又回头去搞.NET Core的WPF的话,你就当我没说过……

本篇讨论了如何将现有的desktop application,在维持已有架构的前提下,转制成APPX放到MS Store提供下载。
当然你们会觉得多出来的Service部分简直不能忍。后续我会进一步介绍如何处理Service部分,不至于让强迫症患者在评论里骂我……
本篇Sample工程的GitHub链接:
https://github.com/manupstairs/UWPWithWCFSample

迁移桌面程序到MS Store(7)——APPX + Service的更多相关文章

  1. 迁移桌面程序到MS Store(8)——通过APPX下载Win32Component

    在上一篇<迁移桌面程序到MS Store(7)——APPX + Service>中,我们提到将desktop application拆分成UI Client+Service两部分.其中UI ...

  2. 迁移桌面程序到MS Store(9)——APPX With Desktop Extension

    在<迁移桌面程序到MS Store(8)——通过APPX下载Win32Component>中我们讨论了通过APPX来下载Service部分的安装包.但是纯UWP的客户端并不能自动运行下载的 ...

  3. 迁移桌面程序到MS Store(14)——APPX嵌入WCF Service以Admin权限运行

    Windows10 1809版本开始,微软又对UWP开放了新的Capability:AllowElevation. 通过这个新的Capability,UWP APP能够在运行时向用户请求Admin权限 ...

  4. 迁移桌面程序到MS Store(5)——.NET Standard

    接下来的几篇,我想讨论下迁移桌面程序到MS Store,可以采用的比较常见.通用性比较强的实施步骤和分层架构. 通常商业项目一般都是不断的迭代,不太可能突然停止更新现有的桌面版本,然后花很长时间从头来 ...

  5. 迁移桌面程序到MS Store(1)——通过Visual Studio创建Packaging工程

    之前跑去做了一年多的iOS开发,被XCode恶心得不行.做人呢,最重要的是开心.所以我就炒了公司鱿鱼,挪了个窝回头去做Windows开发了.        UWP什么的很久没有正儿八经写了,国内的需求 ...

  6. 迁移桌面程序到MS Store(10)——在Windows S Mode运行

    首先简单介绍Windows 10 S Mode,Windows在该模式下,只能跑MS Store里的软件,不能通过其他方式安装.好处是安全有保障,杜绝一切国产流氓软件.就像iOS一样,APP进商店都需 ...

  7. 迁移桌面程序到MS Store(12)——WPF使用UWP InkToolbar和InkCanvas

    我们在<迁移桌面程序到MS Store(4)——桌面程序调用Win10 API>提到了对Win10 API的调用,但仍存在无法在WPF中使用UWP控件的问题,虽然都是XAML控件,但却是两 ...

  8. 迁移桌面程序到MS Store(13)——动态检查Win10 API是否可用

    假设我们现有一个WPF程序,需要支持1903以前的Windows 10版本.同时在1903以后的版本上,额外多出一个Ink的功能.那么我们就可以通过ApiInformation.IsApiContra ...

  9. 迁移桌面程序到MS Store(2)——Desktop App Converter

    迁移传统桌面程序到MS Store的另一种方式是使用Desktop App Converter工具.虽然本篇标题包含了Desktop App Converter(以下简称DAC),实际上我是来劝你别用 ...

  10. 迁移桌面程序到MS Store(3)——开机自启动

    迁移桌面程序的时候,有可能你会遇到这么个需求——开机自启动.Windows传统桌面程序的传统陋习.不论什么奇葩软件都想要开机自启动,默认就给你打开,一开机哐哐哐什么雷,什么企鹅都蹦出来,也不管你用不用 ...

随机推荐

  1. (转贴)fusionCharts属性参考API

    一.FusionCharts的分类 关于FusionCharts的基本介绍我就不在这里浪费篇幅了,想了解的朋友自己去www.baigoogedu.com里面找吧.我就说说FusionCharts的官方 ...

  2. PHP 写文件的例子

    $contents = "All the content"; $dir = 'c:'; $file_path = $dir . "\\content.txt"; ...

  3. django网页图片验证码功能

    在一个正常的登录系统中,验证码是非常重要的,用于识别人机,毕竟我们都知道,这个世界中存在着万恶的爬虫,验证码有很多种方式,有图片的,有邮件的,有短信的,有拼图的,不管什么样的验证码,目的都是验证访问用 ...

  4. Linux运维之docker虚拟化部署nginx

    一.Docker的概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱 ...

  5. MVCS框架的注意点

    1.Service最好用一个接口对应一个service(便于增加扩展方法) 2.除Services和Model外都需继承自各自对应的父类 3.View不要轻易重写Start和Awake方法(含与启动有 ...

  6. mysql之存储引擎和文件配置

    (查看系统服务,在运行里输入services.msc) 补充:将mysql做成系统服务:mysqld --install 取消:mysqld --romove 在服务中可以直接鼠标操作mysql服务的 ...

  7. 将爬取的网页数据保存到数据库时报错不能提交JPA,Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\xB6 \xE2...' for column 'content' at row 1

    错误原因:我们可以看到错误提示中的字符0xF0 0x9F 0x98 0x84 ,这对应UTF-8编码格式中的4字节编码(UTF-8编码规范).正常的汉字一般不会超过3个字节,为什么为出现4个字节呢?实 ...

  8. ZSetOperations 操作解释 拷贝过来的 哈哈哈

    有序集合,默认按照score升序排列,存储格式K(1)==V(n),V(1)=S(1)(K=key,V=value,S=score) 1.add(K,V,S):添加 2.count(K,Smin,Sm ...

  9. STL六大组件

    1.容器 顺序容器.关联容器 2.算法 各种常用算法,sort.search.copy…… 3.迭代器 用来索引容器中元素,是容器与算法之间的胶合剂 4.仿函数(另名函数对象) 仿函数就是让一个类的使 ...

  10. Silverlight样式定义

    方法一.定义在控件内部 <Canvas Background="Red" Height="100" HorizontalAlignment="L ...