整合到右鍵選單
如有錯誤,歡迎指出
在資源管理器中,空白處右鍵(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)右擊,彈出選單的內容。
這裡根據子項cmd
,做一個簡單的解釋:
cmd
cmd\command
Extended
,空值,擁有該資料項意味著當按住shift
鍵右擊時,才可看到該選單項,否則按住shift
與否,均可看到;
HideBasedOnVelocityId
,檢視Powershell
可發現其擁有ShowBasedOnVelocityId
,這兩個資料項決定了,誰隱藏,誰顯示;
MUIVerb
:選單項的顯示文字。如果沒有該資料項,則顯示(預設)
資料項的值(雖然在cmd
中,看起來很奇怪),如果(預設)
未設定值或為空值,則顯示為項名稱;
command
子項,(預設)
資料項:即為要執行的命令,其中%V
表示當前目錄,是登錄檔內建的變數;
若傳遞了錯誤的登錄檔變數,甚至會導致 explorer.exe 程式重啟。
Icon
:.ico
圖示檔案的路徑;
SubCommands
:二級選單項列表,用;
分隔,對應實體位於HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\
中。
有趣的是,當
(預設)
被設定為空值或其它值後,可以看到標誌著存在二級選單的>
,但卻無法彈出二級選單;另外,如果列表中對應的項不存在,也同樣無法彈出二級選單。
啟動方式
在開始選單中,有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中,還有一些其它方案:
- https://gist.github.com/magthe/a60293fe395af7245a9e
- 右鍵選單整合,通過呼叫
mintty.exe
啟動。
- 右鍵選單整合,通過呼叫
- https://github.com/msys2/msys2-launcher
- 該專案提供了
msys2.exe
、mingw64.exe
、mingw32.exe
,它們分別讀取同名的.ini
檔案,以啟動對應的子系統。
- 該專案提供了
- https://gist.github.com/elieux/ef044468d067d68040c7
- 右鍵選單整合,通過呼叫
msys2-launcher
中的.exe
啟動。(無黑框)
- 右鍵選單整合,通過呼叫
事實上,上面的幾個方案最終都呼叫了mintty.exe
。
最終方案
上面已經說明了如何通過修改登錄檔新增右鍵選單,並給出了msys2
的一種啟動方式,但該方法並不完美。
The idea
在Lauchers的最後,The idea部分,說到:
如果你需要正確啟動一個shell,但上面提及的方法中又沒有適合的,那麼可以基於下面的知識來制定你自己的方法:
- 在環境中設定
MSYSTEM=...
,其值可為MSYS
,MINGW32
,或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
- 啟動為 login shell 時被執行,如果已存在
-
.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
以及上一步中得到的環境變數,進一步設定環境,如PATH
,MANPATH
- 根據 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"
巧的是,這樣一來,不論是從“開始”選單中快捷方式啟動,還是從右鍵選單中啟動,它們在工作列上都被合併在了一起。