10 個實驗搞懂命令提示符

前言

相信,不少小夥伴兒都在命令提示符中執行過 ipconfig 查看 ip 信息。咱們還能夠執行 ping ipping 對應的 ip 地址,執行 notepad 啓動記事本,執行 explorer 啓動文件管理器…… windows

可是,你好奇過背後的運做機制嗎?爲何輸入幾個簡單的幾個字母就能啓動外部程序,本文試圖經過一系列實驗來挖掘其背後的運做機制。bash

若是你對下面的問題有很明確的答案,本文不是爲你準備的。若是有模糊,拿不許的地方,請耐心讀完。若是以爲有用,請幫忙點個在看,拜謝。測試

Five Questions

一、在命令提示符裏輸入 notepad,是哪一個位置的記事本被啓動了?跟什麼有關?ui

二、若是同一個目錄下有兩個名爲 bcn 的文件,一個是 bcn.com, 一個是 bcn.exe。在命令提示符中輸入 bcn 會執行哪一個?受什麼影響?spa

三、你知道怎麼讓本身的程序能夠直接在命令提示符中被啓動嗎?像執行 ipconfig 那樣。3d

四、若是 PATH 環境變量是空的,會有什麼問題?日誌

五、若是 PATHEXT 變量是空的,會有什麼問題?code

PATH 實驗

實驗1:在命令提示符中輸入一個不存在的命令(好比,bcn),使用 process monitor 觀察整個過程。cdn

如咱們所料,找不到。結果以下圖:blog

can-not-find-bcn

在觀察 process monitor 捕獲的日誌以前,咱們先查看當前命令提示符的當前路徑( Current Directory)和 PATH 環境變量的值。

current directory的值

PATH環境變量的值

下圖是使用 process monitor 捕獲的事件,已過濾無關信息。

procmon-filter-event-bcn

紅色高亮部分是當前路徑相關的事件,黃白相間的部分是 PATH 環境變量相關的事件。

今後能夠比較有信心的猜想:在命令提示符中輸入命令會先在當前路徑下查找,再到 PATH 環境變量指定的路徑依次查找。

實驗2: 添加一個不存在的路徑到 PATH 環境變量中,再次觀察整個過程。

:: 更新 PATH 環境變量set PATH=%PATH%d:\not_existed_folder:: 執行命令bcn複製代碼

當前路徑沒變,而對應的 PATH 已經多了一條 d:\not_existed_folder,以下圖:

path-with-invalid-folder

下圖是使用 process monitor 捕獲的相關事件(已過濾無關事件)。跟上面的實驗對比,發現只多了黃色高亮部分。

procmon-filter-event-with-not_existed_folder

注意對比上圖中黃色和紅色部分。紅色部分對應的路徑是存在的,因此有三條記錄。黃色部分對應的路徑是不存在的,只有一條記錄。能夠雙擊某條記錄,查看對應的調用棧。相信查看過調用棧後,你會和我同樣,對 Operation 這一列有一個新的認識。

callstack

實驗3:bcn.exe 放到當前路徑( C:\Users\bcn\Desktop)下,執行 bcn

start-bcn-on-current-folder

從上圖可知,啓動的是 C:\Users\bcn\Desktop\bcn.exe,由於在當前路徑下就找到了對應的程序,因此並無到 PATH 環境變量指示的路徑中查找。

實驗4: 刪除 C:\Users\bcn\Desktop\bcn.exe,把 bcn.exe 放到 PATH 環境變量中的 c:\windows\ 下,再次執行 bcn

start-bcn-on-current-folder

從上圖可知,啓動的是 C:\Windows\bcn.exe,在當前路徑下沒找到,而後依次到 PATH 環境變量指示的路徑中查找,在c:\windows\ 下找到了對應的程序。

實驗5: 清空 PATH 環境變量,在命令提示符中輸入 ipconfig,看看是否能正常運行。

Snipaste_2020-05-05_12-49-10

結論:

經過以上幾個實驗,咱們知道了在命令提示符中執行一個命令時的查找順序是:當前路徑,PATH 環境變量中指定的路徑(按出現順序進行查找)。

PATHEXT 實驗

相信有細心的小夥伴兒發現了,在上面的 實驗3實驗4 中,會先查找 bcn.COM,沒找到才繼續查找的 bcn.exe。爲何是這種行爲呢?跟什麼有關呢?咱們看下 PATHEXT環境變量的值,以下圖:

pathext

咱們發現 .COM 出如今 .EXE 以前,是否是這個緣由呢?讓咱們作實驗來驗證。

實驗6: 觀察 PATHEXT 是否會影響查找結果。

調整 PATHEXT 的值爲 .BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.EXE;.COM,若是查找了前面的幾個後綴,而沒查找 .COM,說明 PATHEXT 會影響查找結果。

set PATHEXT=.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.EXE;.COMbcn複製代碼

process monitor 捕獲的事件驗證了咱們的猜想。截圖:

pathext-search-order

實驗7: 觀察 PATHEXT 時的行爲。

清空 PATHEXT,再執行 bcn

set PATHEXT=bcn複製代碼

process monitor 捕獲相關事件以下圖:

excute-with-empty-pathext

有點意外,本來覺得會執行失敗。看來若是 PATHEXT 是空,會使用默認的 PATHEXT,默認的 PATHEXT 是什麼呢?

實驗8: 觀察默認的PATHEXT

重命名 bcn.exebcn.xyz(很重要),而後執行下面的命令:

set PATHEXT=bcn複製代碼

process monitor 捕獲相關事件以下圖:

default-pathext

在個人系統(win10 1903)中,當 PATHEXT 爲空時,默認搜索的擴展名是 .COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC;。其它系統可能有不一樣的行爲,感興趣的小夥伴兒請自行實驗。

實驗9: 當前目錄下同時存在 bcn.combcn.exe 會執行哪一個?(經過上面的實驗,結論很明顯了)

分別執行下面兩組命令,觀察對比結果:

set PATHEXT=.COM;.EXEbcn複製代碼
set PATHEXT=.EXE;.COMbcn複製代碼

procmon 捕獲的兩次查找過程對比圖,黃色是設置 .COM 優先的結果,紅色是設置 .EXE 優先的結果。

compare-load-order

從結果能夠進一步肯定,優先查找 PATHEXT 中先出現的後綴名。

實驗10:觀察直接執行 bcn.exe 觀察查找過程。

run-with-extension

若是命令中帶後綴,那麼查找的時候不會依賴 PATHEXT ,會直接執行給定的命令。

實驗代碼

若是你也想本身動手實驗。能夠新建一個工程,並粘貼下面的代碼,編譯生成測試程序。

#include "stdafx.h"#include <windows.h>#include <stdio.h>#include "stdlib.h"int main(int argc, char* argv[]){ char exe_path[MAX_PATH] = { 0 }; ::GetModuleFileNameA(NULL, exe_path, MAX_PATH); printf("%s\n", exe_path); system("pause"); return 0;}複製代碼

總結

相信經過上面一系列的實驗,咱們對命令提示符如何執行一個外部命令有了深入的認識。對 PATHPATHEXT 這兩個環境變量的做用,簡單總結以下:

  1. PATH 決定了外部命令所在位置的查找順序,PATHEXT 決定了外部命令的擴展名查找順序。
  2. 當咱們在命令提示符中輸入一個命令時,會先到當前路徑(Current Directory)中查找,若是找不到,纔會到環境變量 PATH 指示的路徑中查找。
  3. 若是輸入的命令不帶後綴,那麼會根據 PATHEXT 指示的後綴順序依次拼接成完整名稱再查找。
  4. 若是輸入的命令帶後綴,不會根據 PATHEXT 中的後綴查找。
  5. 若是咱們想讓本身的程序也能直接經過命令提示符啓動,咱們能夠把程序所在路徑添加到 PATH 環境變量中,位置越靠前,越有可能被執行。
  6. 若是 PATHEXT 爲空,那麼會使用默認的 PATHEXT,我機器上的值是 .COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC;
相關文章
相關標籤/搜索