最近在开发应用的过程中,我遇到了如标题所述的需求,其实主要是为了能够快捷启动应用,正像我们可以在“运行”对话框中可以输入一些可执行程序的名称后,就能够直接启动它;这样做,可以增加 App 的易用性。在查了一些文档后,得知在 Windows Build 16266 之后,就加入相关的 API,因此要使用实现以及使用这一功能,Window 系统和 SDK 的版本都要大于 16266,Fall Creators Update (Build 16299) 则完全满足这一条件。

实现

要使用命令行启动 UWP 应用,其实非常简单,只需要两步:首先,在 Package.appxmanifest 中添加 appExecutionAlias 扩展;然后,在 App.OnActived 事件中做相应的处理。

1. 修改Package.appxmanifest

右击项目中的 Package.appxmanifest 文件,在快捷菜单中选择“打开方式“->”XML 文本编辑器“。打开后,对它的内容按照以下试修改:

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
  IgnorableNamespaces="uap mp uap5">
  ...
  <Applications>
    <Application
        ...
      <Extensions>
          <uap5:Extension
            Category="windows.appExecutionAlias"
            Executable="TestCmdLineApp.exe"
            EntryPoint="TestCmdLineApp.App">
            <uap5:AppExecutionAlias>
              <uap5:ExecutionAlias Alias="App.exe" />
            </uap5:AppExecutionAlias>
          </uap5:Extension>     
      </Extensions>
    </Application>
  </Applications>
  ...
</Pakage>

其中加粗部分是我们需要补充的内容。可以看到,我们添加了一个名为 appExecutionAlias  的扩展 (Extension)。在 Extension 节点中包括了几个属性,它们的意义分别如下:

1) Category 属性指明 Extension 的类别,对于我们当前的需求,它的值固定为 windows.appExecutionAlias,即为应用的运行提供别名;
2) Executable 属性指明当前应用的 exe 名称,也即:程序集名称 + ".exe";
3) EntryPoint 属性指明当前应用的入口点,也即 App 类的完整名称(包含其所在的命名空间);
4) 在 AppExecutionAlias\ExecutionAlias  节点中的 Alias 属性,就是我们为要为当前应用定义的命令行启动名称;这里需要说明三点:

a) 它可以与前面 Executable 属性值相同,也可以不同,比如更简短一些,便于用户记住与输入;
b) 如果定义的别名,已经被当前机器上安装的其它应用占用了,那么它就不会生效,也即,谁先占用就对谁有效(当然,如果先前占用的应用被卸载了,那么这个别名就可以被你的应用使用);
c) 可以添加多个 ExecutionAlias  节点,为应用指定多个别名。通过为应用提供更多的别名,可以解决别名被占用的问题(如果确实存在这个问题)。

2. 处理 OnActivated 事件

在 App.OnActived 事件中,我们对 IActivatedEventArgs 参数类型判断,如果其 Kind 属性为 CommandLineLaunch,则认为是命令行启动,接下来所做的就像在 OnLaunched 事件中一样,对 Frame 初始化并导航到应用的主页,如下:

        protected override void OnActivated(IActivatedEventArgs args)
        {
            if (args.Kind == ActivationKind.CommandLineLaunch)
            {
                // ...
            }

            Frame rootFrame = Window.Current.Content as Frame;

            if (rootFrame == null)
            {
                rootFrame = new Frame();
                rootFrame.NavigationFailed += OnNavigationFailed;
                Window.Current.Content = rootFrame;
            }

            rootFrame.Navigate(typeof(MainPage));

            Window.Current.Activate();
            base.OnActivated(args);
        }

3. 参数处理

使用命令行启动应用有一个很大的好处,用户在启动时可以携带参数,如: app.exe a, app.exe a b, app.exe /type:a 等,而应用则根据用户提供的参数作相应的处理。要得到用户传递的参数,只要将 IActivatedEventArgs 类型的参数转换为  CommandLineActivatedEventArgs,通过它的  Operation.Arguments 属性即可得到,剩下的就是对参数进行分析并根据参数进行相应的处理。除了参数,我们也能够得到用户是从哪个目录启动 App 的,这是通过 Operation.CurrentDirectoryPath 属性得到的。完整代码如下:

        protected async override void OnActivated(IActivatedEventArgs args)
        {
            string arugment = string.Empty;

            if (args.Kind == ActivationKind.CommandLineLaunch)
            {
                var cmdArgs = args as CommandLineActivatedEventArgs;
                StringBuilder sb = new StringBuilder();
                sb.AppendLine($"Argument: {cmdArgs.Operation.Arguments}");
                sb.AppendLine($"CurrentDirectoryPath: {cmdArgs.Operation.CurrentDirectoryPath}");
                await new MessageDialog(sb.ToString()).ShowAsync();
            }

            Frame rootFrame = Window.Current.Content as Frame;

            if (rootFrame == null)
            {
                rootFrame = new Frame();
                rootFrame.NavigationFailed += OnNavigationFailed;
                Window.Current.Content = rootFrame;
            }

            rootFrame.Navigate(typeof(MainPage), arugment);

            Window.Current.Activate();
            base.OnActivated(args);
        }

最后,要测试效果,需要部署(Deploy)应用。

部署完成后,在“运行”(Win + R)对话框中输入上面定义的别名(和参数),即可。当然,在“命令提示符”窗口甚至在“资源管理器”窗口的地址栏中,你都可以输入别名来启动应用。

背后原理

为什么在上述这些位置我们输入别名后,就可以运行应用呢?为了解决这个问题,首先我们使用 where 命令得看看对应的命令究竟在哪里。在“命令提示符”窗口中,输入: where 别名,得到这样的结果:

C:\Users\Admin>where app
C:\Users\Admin\AppData\Local\Microsoft\WindowsApps\App.exe

在“资源管理器”中打开对应的路径,会看到在这个目录下存放了当前机器中所有那些使用别名的应用,其实这里的文件可以认为是一个快捷方式。

不仅如此,这个目录也在 PATH 环境变量中(可在“命令提示符”中使用 path 命令查看或在“系统属性”的“环境变量”对话框中查看),因此,我们才可以在任何位置都能启动应用。

除此以外,作用用户,我们还可以在桌面(或其它任何目录)为应用创建快捷方式,右击桌面->创建快捷方式,然后输入别名 和参数(可选)。通过双击快捷方式图标,也可以启动应用。这一点类似于创建磁贴,不过,它要比磁贴更灵活。我们甚至还可以为不同的参数创建多个快捷方式,也可以为每个快捷方式指定不同的图标。这样,是不是感觉更像 Win32 应用了呢?

总结

本文主要提到了如何使用命令行来启动 UWP 应用,为应用提供这一特性可以为其增加易用性以及灵活性。作为 App 的使用者,可以更便利、更灵活地打开、使用应用。这样,使得 UWP 应用和 Win32 程序的行为更加一致。

参考资料:

Command-Line Activation of Universal Windows Apps

UWP: 通过命令行启动 UWP 应用的更多相关文章

  1. win10 uwp 使用 msbuild 命令行编译 UWP 程序

    原文:win10 uwp 使用 msbuild 命令行编译 UWP 程序 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http:// ...

  2. Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式

    昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册. 下面将会通过几个部分简单的介绍CLI在应用中的使用场景. 昨天已经联系过几个基本的命令行参数 ...

  3. sublime text2在windows中以命令行启动

    sublime text2在windows中以命令行启动   把执行文件添加到PATH中即可,如图: 如果你和我一样习惯了mac下的简写subl,那么需要在程序目录中新建一个批处理文件subl.bat ...

  4. Apache Commons CLI命令行启动

    今天又看了下Hangout的源码,一般来说一个开源项目有好几种启动方式--比如可以从命令行启动,也可以从web端启动.今天就看看如何设计命令行启动... Apache Commons CLI Apac ...

  5. 记一次使用命令行启动部署在tomcat上的应用

    在Eclipes进行程序开发完成后,一般都会直接在Eclipse部署启动,其中的一些启动参数设置都会在其中进行,若用命令行启动,则需要手动配置. 程序开发完成后打成的war包,需要部署到Tomcat应 ...

  6. 转载:使用命令行启动VirtualBox虚拟机

    使用命令行启动VirtualBox虚拟机 装上VirtualBox就琢磨着如何让它开机自动启动,又或者能够通过命令行的形式直接启动指定的虚拟机. 看了下VirtualBox的官方文档,发现有一个命令可 ...

  7. Android中使用am命令实现在命令行启动程序详解

    在Android中,除了从界面上启动程序之外,还可以从命令行启动程序,使用的是命令行工具am. 复制代码代码如下: usage: am [subcommand] [options] start an ...

  8. 如何设置fedora默认从命令行启动?

    Sumary:因为在fedora中没有/etc/initab文件我们不方便从这里设置它的runlevel target,但是linux又给我们提供了一个强悍的工具systemd,我们可以用system ...

  9. vmware 命令行启动虚拟机

    在redhat enterprise 5.3安装了vmware workstation,如何用vmware 命令行启动指定虚拟机?/usr/bin/vmware[root@node0 ~]# /usr ...

随机推荐

  1. 关于使用Log4Net将日志插入oracle数据库中

    1.关于配置文件. <?xml version="1.0" encoding="utf-8" ?> <configuration> &l ...

  2. MySQL:表的操作 知识点难点总结:表完整性约束及其他常用知识点二次总结🙄

    表操作 一 : 修改表表表表表表表表表: ALTER TABLE 语法 1. 改表名rename alter table 表名 rename 新表名 2. 增加字段add alter table 表名 ...

  3. Django学习日记03_模型_Fields

    创建模型 模型对应工程中的应用,一个工程可能包含很多的应用,通过命令 python manage.py startapp myapp 创建一个叫myapp的应用,django会帮助生成以下目录: po ...

  4. Head First设计模式之命令模式

    一.定义 定义:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化.对请求排队或记录请求日志,以及支持可撤消的操作. 主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关 ...

  5. 微信小程序入门指南

    本文同步发布在 https://www.cssge.com 因为下个项目需要用微信小程序来开发,所以就找了小程序开发文档来研究.下面记录一下微信小程序的主要开发流程和语法. 账号注册 开发小程序的第一 ...

  6. Windows和Linux下换行的不同

    因为测试IM会用到一些账号,于是写了一段代码从数据库里把需要的用户名.密码和手机号都一一取了出来,然后放到NotePad++中做进一步的处理. 取用户名.手机号和密码的代码如下: public cla ...

  7. 在block内如何修改block外部变量

    默认情况下,在block中访问的外部变量是复制过去的,即:写操作不对原变量生效.但是你可以加上__block来让其写操作生效,示例代码如下: 1 2 3 4 5 6 __block int a = 0 ...

  8. HTML知识点之表示强调的主要元素

    <h1>~<h6> 在HTML中,标题(Heading)元素共有6个级别的标签:<h1>~<h6>.它们都是块级元素.标题数字越小,字体就会越大,标题的 ...

  9. 从Unity中的Attribute到AOP(八)

    本文将讲一下在UnityEditor命名空间下的一些特性. CallBackOrder,这个Attribute是所有带callback index的Attribute的基类,由于官方也没有给出详细的说 ...

  10. IdentityServer Topics(4)- 登录

    为了使IdentityServer代表用户发布令牌,该用户必须登录到IdentityServer. Cookie认证 使用来自ASP.NET Core的cookie身份验证处理程序管理的cookie跟 ...