zoukankan      html  css  js  c++  java
  • UWP使用命名管道与桌面程序通信 (C#)

    关于UWP的历史,其起源是Microsoft在Windows 8中引入的Metro apps。(后来又被称作Modern apps, Windows apps, Universal Windows Apps等)无论是从目的还是从效果上看,这一类应用模型都与iOS/Android比较相似,是为了更有利于移动平台生态的发展设计的。
    然而UWP目前面向的最大的用户群体是Windows桌面用户,只用UWP实现一个程序就会出现很多feature无法实现的问题,因此这种情况下,让用户安装并运行一个普通权限的后台进程,使用UWP做UI与之通信就成为了一种选择,毕竟UWP的C#/XAML性能比WPF好得多,分发/支付上也比桌面程序方便不少,虽说原则上微软并不允许商店应用与桌面应用互相通信。

    除了命名管道(named pipe),进程间通信的方式还有很多,比如Socket,还有微软给Runtime Broker用的COM RPC(rpcrt4)等。对于前者,如果是AppContainer默认的防火墙配置,与本机其它程序不允许通过127.0.0.1通信,而调节这个防火墙配置需要管理员权限。而对于COM RPC,由于其API比较复杂,并且rpc.h里大部分的API是desktop only,因此调用起来也不方便。(在Store apps里有办法使用desktop only API,但是如果数目多了会比较麻烦)

    相比之下,命名管道只需要在app中获取一个desktop only的API(即CreateFile)就能使用了,并且用户运行桌面程序时不需要管理员权限,大概是最简单的方式。

    在AppContainer中不能创建命名管道,只能连接到有权限访问的命名管道。因此我们使用桌面程序创建。

    桌面程序:

    using (var pipe = new NamedPipeServerStream("mypipe", PipeDirection.InOut, -1, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, null, HandleInheritability.None, PipeAccessRights.ChangePermissions))  
    {
        PipeSecurity ps = pipe.GetAccessControl();
        PipeAccessRule clientRule = new PipeAccessRule(
            new SecurityIdentifier("S-1-15-2-1"), // All application packages
            PipeAccessRights.ReadWrite,
            AccessControlType.Allow);
        PipeAccessRule ownerRule = new PipeAccessRule(
            WindowsIdentity.GetCurrent().Owner,
            PipeAccessRights.FullControl,
            AccessControlType.Allow);
        ps.AddAccessRule(clientRule);
        ps.AddAccessRule(ownerRule);
        pipe.SetAccessControl(ps);
        pipe.WaitForConnection();
        using (var sr = new StreamReader(pipe, Encoding.UTF8))
        {
            while (true)
            {
                string message = sr.ReadLine();
                //在此处处理App写入命名管道的内容
                pipe.WaitForPipeDrain();
            }
        }
    }

    其中”mypipe”是命名管道的名称,SID S-1-15-2-1 是All application packages的SID,如果只想让一个AppContainer访问,可以通过获取进程信息来获取它的SID。

    App程序:

    var handle = CreateFileW(@"\\.\pipe\mypipe", FileAccess.ReadWrite, FileShare.None, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);  
    if (handle.IsInvalid)  
    {
        var err = Marshal.GetLastWin32Error();
        //handle error
    }
    sw = new StreamWriter(new FileStream(handle, FileAccess.Write), Encoding.UTF8);  
    sw.WriteLine("Hello from AppContainer");  
    sw.Flush(); 

    其中”mypipe”是命名管道的名称。
    由于UWP的.NET标准库并没有System.IO.Pipes,必须手动调用CreateFile。UWP允许使用的CreateFile2是不能打开命名管道的,即使有权限也会返回ERROR_NOT_SUPPORTED_IN_APPCONTAINERCreateFileW并不能直接使用DllImport("kernel32"),否则无法通过WACK。

  • 相关阅读:
    node-express脚手架生成的项目中实现浏览器缓存
    three.js通过canvas实现球体世界平面地图
    激光原理与技术(第二版)课后答案 阎吉祥 版 高等教育出版社 课后习题答案 解析
    Spring2.5注释驱动与基于注释的MVC
    iBatis2学习笔记:入参和返回值的问题
    重写了java.util.Date类中一些过时的方法
    Java日期格式化及其使用例子收集
    深入研究java.lang.ThreadLocal类
    Java:对象的强、软、弱和虚引用
    Java 反射机制深入研究
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14304942.html
Copyright © 2011-2022 走看看