[msys2]集成到右键菜单

集成到右键菜单

如有错误,欢迎指出

在资源管理器中,空白处右键(right-clicking on folder backround in Windows Explorer)会弹出菜单,其中有如“在此处打开cmd”等选项,这些选项显著提高了“工作”效率。这篇文章所要讲述的即为:“如何将MSYS2集成到右键菜单中——编辑注册表”。

背景知识

注册表

资源管理器“右键菜单”的注册表项位于HKCR\Directory\中。其中,Background\shell\决定了在空白处右击(right-clicking on folder backround in Windows Explorer),弹出的菜单内容;shell\决定了在文件夹上(on folder itself)右击,弹出菜单的内容。

[msys2]集成到右键菜单

这里根据子项cmd,做一个简单的解释:

cmd

[msys2]集成到右键菜单

cmd\command

[msys2]集成到右键菜单

Extended,空值,拥有该数据项意味着当按住shift键右击时,才可看到该菜单项,否则按住shift与否,均可看到;

HideBasedOnVelocityId,查看Powershell可发现其拥有ShowBasedOnVelocityId,这两个数据项决定了,谁隐藏,谁显示;

MUIVerb:菜单项的显示文本。如果没有该数据项,则显示(默认)数据项的值(虽然在cmd中,看起来很奇怪),如果(默认)未设置值或为空值,则显示为项名称;

command子项,(默认)数据项:即为要执行的命令,其中%V表示当前目录,是注册表内置的变量;

若传递了错误的注册表变量,甚至会导致 explorer.exe 进程重启。

此外,可以参考 https://superuser.com/questions/136838/which-special-variables-are-available-when-writing-a-shell-command-for-a-context

Icon.ico图标文件的路径;

SubCommands:二级菜单项列表,用;分隔,对应实体位于HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\中。

有趣的是,当(默认)被设置为空值或其它值后,可以看到标志着存在二级菜单的>,但却无法弹出二级菜单;另外,如果列表中对应的项不存在,也同样无法弹出二级菜单。

[msys2]集成到右键菜单

启动方式

在开始菜单中,有MSYS2 64bit,其中有三个快捷方式分别用于启动MSYS2的三个子系统。

C:\Users\xxxx\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MSYS2 64bit

查看属性可知,它们都调用了一个叫做msys2_shell.cmd的脚本,该脚本位于MSYS2安装目录下,传递/?查看以可用选项。

结合 bat常用命令 以帮助阅读该脚本。

注册表文件

注册

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\Background\shell\MSYS2]
"MUIVerb"="Open MSYS2 Here"
"Extended"=""
"SubCommands"="MSYS2.MSYS;MSYS2.MinGW 64-bit"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MSYS]
"MUIVerb"="MSYS"
"Icon"="D:\\msys64\\msys2.ico"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MSYS\command]
@="D:\\msys64\\msys2_shell.cmd -msys -here"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MinGW 64-bit]
"MUIVerb"="MinGW 64-bit"
"Icon"="D:\\msys64\\mingw64.ico"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MinGW 64-bit\command]
@="D:\\msys64\\msys2_shell.cmd -mingw64 -here"

删除

Windows Registry Editor Version 5.00

[-HKEY_CLASSES_ROOT\Directory\Background\shell\MSYS2]
[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MSYS]
[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MinGW 64-bit]

其它启动方案

上面通过使用msys2_shell.cmd启动,可以很明显地看到闪现出一个cmd黑框,这是运行批脚本无法避免的问题。

但通过开始菜单中的快捷方式启动时,几乎看不到黑框。

Lauchers中,还有一些其它方案:

事实上,上面的几个方案最终都调用了mintty.exe

最终方案

上面已经说明了如何通过修改注册表添加右键菜单,并给出了msys2的一种启动方式,但该方法并不完美。

The idea

Lauchers的最后,The idea部分,说到:

如果你需要正确启动一个shell,但上面提及的方法中又没有适合的,那么可以基于下面的知识来制定你自己的方法:

  • 在环境中设置MSYSTEM=...,其值可为MSYSMINGW32,或MINGW64
  • 而后运行一个 login shell

如果条件限制你只能使用一行语句,那么典型的写法是:

C:/msys64/usr/bin/env MSYSTEM=MSYS /usr/bin/bash -li

另外,如果需要保持当前工作目录,那么还需要设置CHERE_INVOKING=1;如果你需要运行一个特定的命令而非 interactive shell,你仍需要通过一个 login shell 来运行,如:... /usr/bin/bash -lc python

shell 启动脚本

在用户主目录中,有三个启动脚本:

  • .bash_profile

    • 启动为 login shell 时被执行
    • 该脚本中调用了~/.bashrc
  • .profile

    • 启动为 login shell 时被执行,如果已存在~/.bash_profile~/.bash_login,则不执行
    • 该脚本中调用了~/.bashrc
  • .bashrc

    • 启动为交互式shell 时被执行
    • 当仅启动为 login shell 时,该脚本仍会被调用,但根据语句[[ "$-" != *i* ]] && return,该脚本将立即退出

可以发现以上脚本均不包含与子系统相关的内容,下面考察/etc内的几个启动脚本:

  • msystem
    • 该脚本由profile调用
    • 环境变量MSYSTEM说明了启动那个子系统,根据语句export MSYSTEM="${MSYSTEM:-MSYS}"可知,若未指定MSYSTEM,则默认为MSYS
    • 根据MSYSTEM设置如下环境变量:
      • MSYSTEM_PREFIX MSYSTEM_CARCH MSYSTEM_CHOST MINGW_CHOST MINGW_PREFIX MINGW_PACKAGE_PREFIX CONFIG_SITE
      • 如果子系统为MSYS,则上述不包含前缀MINGW_的变量
  • profile
    • System-wide profile file
    • 根据环境变量MSYS2_PATH_TYPE(默认为minimal)设置环境变量ORIGINAL_PATH,而后该变量将参与设置PATH
    • 调用/etc/msystem
    • 根据MSYSTEM以及上一步中得到的环境变量,进一步设置环境,如PATHMANPATH
    • 根据 shell(bash、ksh、zsh),调用/etc/profile.d/中的脚本
  • bash.bashrc
    • System-wide bashrc file

CHERE_INVOKING

这是一个神秘的变量,通过设置该变量,可以使打开的 shell 保留当前工作目录,而不是自动修改为用户主目录。在Starting in a particular directory中说明了这一作用。在msys2-launcher的源码和msys2_shell.cmd中都可以看到该变量的身影。

但奇怪的是,我没有在任何 shell 启动脚本中找到这一变量,所以我不知道它在何处起了作用,但它又的的确确起了作用。

Windows 任务栏图标

参考Taskbar icon grouping,任务栏上的图标会根据图标本身和启动命令进行自动合并,也可通过设置AppID来提供更优先的合并依据。

综述

考虑到“开始”菜单里的快捷方式是安装msys2时自动创建的,所以这里就不再对其做出修改了。

综上所述,得到注册表文件如下:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\Background\shell\MSYS2]
"MUIVerb"="Open MSYS2 Here"
"Extended"=""
"SubCommands"="MSYS2.MSYS;MSYS2.MinGW 64-bit"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MSYS]
"MUIVerb"="MSYS"
"Icon"="D:/msys64/msys2.ico"

; 开始的可执行文件路径必须用反斜杠(back-slash)形式。尽管使用斜杠(slash)在资源管理器中
; 是有效的,但在注册表中是无效的。
; mintty 的选项 --dir \"%V/\" 是没有必要的。
; 这里的 title 和 msys2_shell.cmd 中的保持了一致。
; 将 env 放在前面也可以启动,但会闪现黑框,这是因为 env 是命令行程序,需要在终端中执行,
; 而默认终端即为 cmd;而 mintty 为图形程序。
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MSYS\command]
@="D:\\msys64\\usr\\bin\\mintty -i /msys2.ico -t \"MSYS2 MSYS\" /bin/env MSYSTEM=MSYS CHERE_INVOKING=1 /usr/bin/bash -li"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MinGW 64-bit]
"MUIVerb"="MinGW 64-bit"
"Icon"="D:/msys64/mingw64.ico"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\MSYS2.MinGW 64-bit\command]
@="D:\\msys64\\usr\\bin\\mintty -i /mingw64.ico -t \"MinGW x64\" /bin/env MSYSTEM=MINGW64 CHERE_INVOKING=1 /usr/bin/bash -li"

巧的是,这样一来,不论是从“开始”菜单中快捷方式启动,还是从右键菜单中启动,它们在任务栏上都被合并在了一起。

发表评论

相关文章