[msys2]整合到右鍵選單

z發表於2021-03-03

整合到右鍵選單

如有錯誤,歡迎指出

在資源管理器中,空白處右鍵(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)右擊,彈出選單的內容。

image-20210220211323843

這裡根據子項cmd,做一個簡單的解釋:

cmd

cmd\command

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\中。

有趣的是,當(預設)被設定為空值或其它值後,可以看到標誌著存在二級選單的>,但卻無法彈出二級選單;另外,如果列表中對應的項不存在,也同樣無法彈出二級選單。

image-20210221001313520

啟動方式

在開始選單中,有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"

巧的是,這樣一來,不論是從“開始”選單中快捷方式啟動,還是從右鍵選單中啟動,它們在工作列上都被合併在了一起。

相關文章