• 析命令提示符的原理


    前言

     

    启动命令提示符后,是否有这些疑问:

    1. 为什么执行ipconfig,可以直接查询到IP信息
    2. 为什么执行ping ip,可以查询到对应的主机状态。响应、未响应。
    3. 为什么执行notepad,可以启动记事本。
    4. 为什么执行explorer,可以启动文件管理器。

    这些背后的原理会是什么?运作的机制又是什么?为什么输入几个简单的几个字母就能启动外部程序?

    主题

    本次分享围绕这以下五个问题开展:

    1、在命令提示符里输入 notepad,是哪个位置的记事本被启动了?跟什么有关?

    2、如果同一个目录下有两个名为 Testtest的文件,一个是 Testtest.com, 一个是 Testtest.exe。在命令提示符中输入 Testtest会执行哪个?受什么影响?

    3、你知道怎么让自己的程序可以直接在命令提示符中被启动吗?像执行 ipconfig 那样。

    4、如果 PATH 环境变量是空的,会有什么问题?

    5、如果 PATHEXT 变量是空的,会有什么问题?

    验证方式

    (1)PATH验证

    例子1:进入指定的文件夹中,在命令提示符输入一条不存在的命令,观察其搜索过程。

    首先确定,当前命令提示符的路径在哪?相关的PATH参数。避免找错了目标。

     

    PATH有点多,可以选择将其导出文档中。

    命令:echo %PATH% > ./env.txt

     

     接下来,就通过process monitor捕获的事件,看看命令提示符的搜索路径是怎样的。

     

    从上面图中可以看出,蓝色部分就是当前路径相关的事件,其他的都是与PATH环境变量相关的事件。

    可以得出一个小结论:

    • 在命令提示符中输入命令会先在当前路径下查找,再到 PATH 环境变量指定的路径依次查找。

    例子2:添加一个不存在的路径到PATH环境变量中,再次观察整个过程。

    更新PATH环境变量的命令:set PATH=%PATH%E:NotFolder

     可以看出,其他路径都没有改变,但PATH中多出一条E:NotFolder。

    在命令提示符中,再顺便输入一条命令,查看器搜索过程。

     是否发现一个奇怪的点,为什么其他目录有3条记录,而最新添加的PATH却只有1条记录?

    原因:

    • 已存在的路径,普遍有3条记录。分别是:打开、查询、关闭。
    • 不存在的路径,只有1条记录。只有:打开。因为不存在该路径,所以打开失败,不会再有查询操作了

    也可以通过栈的调用过程来观察,如下:

     结论:

    •  本次的例子2进一步验证了,例子1的结论。 PATH 环境变量是依次查找的。
    •  在开发过程中,某环境变量特别重要,尽可能提前到前几个。

     

    回顾下第一个问题:在命令提示符里输入 notepad,是哪个位置的记事本被启动了?跟什么有关?

    例子3:编写一个测试程序(Testtest.exe),放到当前的路径下,通过命令启动,观察正常的启动路径。

    测试程序内容:简单打印出当前程序的路径。

     从上图可知,启动的是 C:UsersLuojialinDesktopTesttestTesttest.exe,因为在当前路径下就找到了对应的程序,所以并没有到 PATH 环境变量指示的路径中查找。

    例子4: 删除当前路径下测试程序(C:UsersLuojialinDesktopTesttestTesttest.exe),并将这个程序移动到C:windows下,同时添加环境变量(Testtest,Testtest.exe),再起启动测试程序。

    注:如果不添加该环境变量,Testtest将会无法识别。

    添加环境变量:set Testtest=Testtest.exe

    查询某个环境变量:echo %Testtest%

     从上图可知,启动的是 C:WindowsTesttest.exe,在当前路径下没找到,然后依次到 PATH 环境变量指示的路径中查找,在c:windows 下找到了对应的程序。

    例子3+例子4的结论:

    • 依次从PATH环境变量中查询,一旦查询到对应的名称且是可执行的,立马执行。不会继续往下查询。

    此处应回顾下第3个问题:你知道怎么让自己的程序可以直接在命令提示符中被启动吗?像执行 ipconfig 那样。

    例子5:清空 PATH 环境变量,在命令提示符中输入 ipconfig,看看是否能正常运行。

    清空环境变量:set PATH=

     清空环境变量后,结果发现:连ipconfig也无法被执行了,但是ipconfig.exe这个程序是存在的。

    大结论:

    • 命令提示符中执行一个命令时的查找顺序是:当前路径,PATH 环境变量中指定的路径(按出现顺序进行查找)。
    • 命令提示符依次从PATH环境变量中查询,一旦查询到对应的名称且是可执行的,立马执行。不会继续往下查询。
    • 环境变量可以被清除,命令启动依赖环境变量;一旦清除环境变量后,对应的命令无法被执行。

    注:因为是在窗口中执行的清除操作,仅针对当前窗口有效,重启后%PATH%会重置为与system一致。如果清除system下的PATH,就会很严重。

    此处应回顾下第4个问题:如果 PATH 环境变量是空的,会有什么问题?

    (2)PATHEXT验证

    在上面的例子3中,会先查找 Testtest.COM,没找到才继续查找的 Testtest.exe。为什么是这种行为呢?跟什么有关呢?

    查看下PATHEXT环境变量的值,如下图:

    提出疑问:.COM 出现在 .EXE 之前,是不是也是依次查询的呢?

    例子6:调整PATHEXT的顺序,是否会影响到查询的结果。

    调整PATHEXT顺序:set PATHEXT=.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.EXE;.COM

    再次执行程序,通过Process monitor捕获的事件,观察。

    从图中可以看出,PATHEXT的查询顺序被调整了。本来是.COM->.EXE;现在是:.BAT->CMD->.....->.EXE->.COM

    小结论:

    • PATHEXT的查询顺序可以被调整,可以被修改。

    例子7:清空PATHEXT,再次观察PATHEXT的行为。

    清空PATHEXT:set PATHEXT=

    通过Process monitor捕获相关的事件:

     

    清空PATHEXT后,原以为会向PATH一样,无法执行成功;但Testtest被执行成功,.COM→.EXE。有点像一开始的设置。

    会不会是默认的PATHEXT?如果是,那么默认的PATHEXT又是什么?

    例子8:修改Testtest的扩展名,修改为Testtest.abcd,观察默认的PATHEXT。

    注:修改扩展名为了能够通过"Testtest"直接进入搜索,同时又不会启动成功,引起中断。

    再次通过Process monitor捕获相关的事件:

    与开始的进行比较(例子6的前面截图),完全就是一模一样啊。这不就是默认的PATHEXT咯。

    小结论:

    • 当 PATHEXT 为空时,默认搜索的扩展名是 .COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC。

    此处就可以回顾下第5个问题:如果 PATHEXT 变量是空的,会有什么问题?

    例子9:当前目录下同时存在 Testtest.com 和 Testtest.exe 会执行哪个?

    单独设置.com与.exe的顺序关系。

    如:

    set PATHEXT=.COM;.EXE

    set PATHEXT=.EXE;.COM

    结果如下:

    procmon 捕获的两次查找过程对比图,PAHTEXT的顺序确实会影响到查询的结果。

    小结论:

    • 优先查找 PATHEXT 中先出现的后缀名。

    此处就可以回顾下第2个问题:如果同一个目录下有两个名为 Testtest的文件,一个是 Testtest.com, 一个是 Testtest.exe。在命令提示符中输入 Testtest会执行哪个?受什么影响?

    例子10:如果明确添加了扩展名,即选择绝对路径。

    不通过程序名称,直接执行Testtest.exe,使用程序的绝对路径,结果又会是什么?查找路径又会是什么?

    注:为了不干扰数据,可以重启机器。使用默认的PATHEXT。

    从图中可以看出,根本就没有搜索.COM,而是直接找到了.EXE;同时,修改扩展名为Testtest.abc,如果Testtest.exe不存在,就会直接执行失败。

    小结论:

    • 如果命令中带后缀,那么查找的时候不会依赖 PATHEXT ,会直接执行给定的命令。

    总结论

    1. PATH决定了外部命令所在位置的查找顺序,PATHEXT 决定了外部命令的扩展名查找顺序。
    2. 当我们在命令提示符中输入一个命令时,会先到当前路径(Current Directory)中查找,如果找不到,才会到环境变量PATH 指示的路径中查找。
    3. 如果输入的命令不带后缀,那么会根据PATHEXT 指示的后缀顺序依次拼接成完整名称再查找。
    4. 如果输入的命令带后缀,不会根据PATHEXT 中的后缀查找。
    5. 如果我们想让自己的程序也能直接通过命令提示符启动,我们可以把程序所在路径添加到PATH 环境变量中,位置越靠前,越有可能被执行。
    6. 如果PATHEXT 为空,那么会使用默认的 PATHEXT,默认值是: .COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC;。(可能也会根据机器决定的,待验证)

    测试程序DEMO

    #include <windows.h>
    #include <stdio.h>
     
    int main(int argc, char* argv[]) {
        char exePath[MAX_PATH] = { 0 };
        ::GetModuleFileNameA(NULL, exePath, MAX_PATH);
        printf("%s
    ", exePath);
        system("pause");
        return 0;
    }
  • 相关阅读:
    【leetcode】1030. Matrix Cells in Distance Order
    【leetcode】1031. Maximum Sum of Two Non-Overlapping Subarrays
    【leetcode】1032. Stream of Characters
    L120 单词造句
    L119
    L118
    2018.8.6邮件规范一
    L117
    L116
    L115
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/15028128.html
Copyright © 2020-2023  润新知