IT评测·应用市场-qidao123.com

标题: 08 Windows批处理之执行编译后的程序 [打印本页]

作者: 曹旭辉    时间: 2024-9-10 11:20
标题: 08 Windows批处理之执行编译后的程序
本文是关于一个bat文件执行或调用另一种语言编写和编译的程序。实际上,这样做的语法非常简单。本文最风趣的方面是,有时正在执行的程序在bat文件中没有定义路径。bat文件如何找到可执行文件?
本文的重要重点将放在查找此类程序的两个非常重要的机制上,即当前目次和路径变量。本主题远远超出了程序的执行。您将在调用其他bat文件时使用它,而且当资源没有使用路径定义时,它会影响许多其他实例。比方,在上文中,我们讨论了许多用于复制、移动、删除和重命名文件的命令。当每个命令中的文件没有在bat文件中定义路径时,所有这些命令都可以在bat文件中很好地工作,但条件是您理解了这些概念。当然,您还将学习调用程序和通报参数的不同方法。
调用可执行文件

通常,bat文件只不外是调用已编译程序(也称为可执行程序)的工具或包装器。bat文件将简单地设置程序所需的一些变量,调用可执行文件,并在后端执行一些错误处理。更复杂的bat文件可能调用几十个不同的程序,甚至可能在某些调用中使用条件逻辑。不管简单还是复杂,批处理的一个特性就是能够调用用其他语言编写的可执行文件。
调用命令接受可执行文件作为它的第一个参数,也可能是唯一的参数。下面的命令调用或执行位于D:\Batch\08\目次下的程序UartAssist.exe:
  1. call D:\Batch\08\UartAssist.exe
复制代码
call命令调用一个程序;这应该不会让人感到惊奇,但事情会变得很希奇。这是批处理中唯一一个在省略命令名本身时运行良好的命令。下面的命令虽然在技术上不是call命令,但执行与前面示例中的call命令类似的功能:
  1. D:\Batch\08\UartAssist.exe
复制代码
思考一下这个问题。命令set x=1设置了一个变量,但是语句x=1只会混淆解释器。如果在robocopy命令的开头省去了文本robocopy,那么头脑正常的人都不会盼望复制剩余的文本。
这险些看起来像把戏,但从程序员的角度来看。当它解释一个新行时,它通常盼望第一项是一个命令。当它找到set时,它会推测一个变量、一个等号和一个值;当它找到robocopy时,它会探求另一组参数。当它发现一些完全出乎意料的东西时,解释器不会夷由;它将返回有问题的内容给到编码人员,假设它是可以执行的,并执行它-就像call命令一样。
一些批处理程序员对可执行文件使用call命令;有些则不然。我属于后一种阵营,更喜欢可执行文件的简洁表面,大概只是在一行代码中有一个已剖析的变量,但我对那些明确地拼写命令的人没有任何疑虑。更重要的是,一致性是关键;坚持你的传统选择。(不管使用哪种方式,重要的是你的代码风格要一致。)
我还喜欢将程序名保存在具有完全限定路径的变量中,仅在尚未定义时设置它。这确保了所需的程序在默认环境下存储在变量中,同时也答应其他人为了机动性将其设置为替换程序:
  1. if not defined UartAssist set UartAssist=D:\Batch\08\UartAssist.exe
复制代码
然后,当必要执行程序时,这个简单的命令(如果我可以称之为命令的话)将调用所需的程序:
  1. %UartAssist%
复制代码
这个变量包含可执行文件的路径,但是让我们回到代码行只包含硬编码的路径和文件名的概念。
你可以通过删除路径来缩短它,只留下程序的名称和扩展名:UartAssist.exe。
这看起来更简单,但是当你停下来思考解释器在机器甚至网络上的什么地方找到程序时,复杂性就增长了。在深入研究这些细节之前,我必要先谈谈两个命令/变量。
cd 命令和变量

cd命令也是一个变量,一个特殊的变量,是少数批处理伪环境变量之一。在后续中,我将对这些变量进行更多的介绍。现在,只需将它们视为解释器最初设置的具有一些独特特性的变量。
该变量表现当前目次。这个命令有点模棱两可,因为它也可以表现更改目次,因为它用于去…好吧,就是更改当前目次。
双击或打开bat文件时,当前目次为该bat文件所在的目次或文件夹。如果从不同的进程调用类似的bat文件,则从该进程继承当前目次。简单地调用不同目次中的bat文件或可执行文件不会改变当前目次,但是cd命令会改变。
下面显示的第一行和末了一行使用cd变量显示当前目次。这个核心是cd命令,它纯熟地将当前目次更改为其参数,假设该目次存在:
  1. > con echo Current Directory is: %cd%
  2. cd D:\Batch\
  3. > con echo Current Directory is: %cd%
复制代码
如果一个包含这三行代码的bat文件位于D:\Batch\08目次下,执行它将显示原来的当前目次和新分配到控制台的当前目次:
  1. Current Directory is: D:\Batch\08
  2. Current Directory is: D:\Batch
复制代码
您也可以设置当前目次相对于现有的当前目次。一个点表现它的现有值,以是这将cd变量分配给一个子目次:
  1. cd .\Child\
复制代码
两个点表现现有当前目次的父目次,以是下面的代码将当前目次向上移动一级:
  1. cd ..
复制代码
你甚至可以将cd变量重新赋值给一个兄弟目次,首先用两个点向上一层:
  1. cd ..\Sibling\
复制代码
我甚至不愿提及这一点,但是chdir是cd命令的批处理同义词。也就是说,前面示例中的命令在功能上等同于chdir ..\Sibling\。但是,cd变量没有同义词,因此可以使用chdir或cd来更改当前目次,但是在剖析当前目次时必要使用cd。我发现将cd用于这两种目的是最简单的。
在讨论当前目次的用途之前,我必要介绍另一个命令,它也是一个变量。
path 命令和变量

与cd非常相似,path也是命令和伪环境变量。该变量是在Windows盘算机上预定义的,其中包含盘算机所需的以分号分隔的目次列表,比方Java和Windows可执行文件的路径。
就像cd命令设置当前目次一样,path命令设置路径变量。在下一行代码中,现有的值被添加到别的两个目次中;请注意,在每个附加目次的末尾插入的分号作为分隔符:
  1. path D:\PrependDir\;%path%;C:\AppendDir\;
复制代码
您可以完全重新分配path变量—如果参数只是一个分号,甚至可以完全删除它。这个变量中的各种目次的存在是有目的的,可能答应一些必要的进程运行。要非常谨慎地在机器上持久地更改变量,比方使用setx命令,但是前面显示的path命令只更改执行bat文件的路径。在最坏的环境下,你可能会破坏你的bat文件,但你不会破坏你的电脑上的任何其他东西。在下一节中,我将解释为什么您可能希望更改path变量。
警告:
set命令提供了重置cd和path变量的另一种方法,但是出于一致性思量,我拒绝使用这种方法,因为其他一些伪环境变量不能或不应该使用该命令重置,而且它必要更多的按键操纵。
查找可执行文件

让我们回到简单地通过调用程序的名称和扩展名来执行程序,就像这样:UartAssist.exe。
解释器在哪里找到可执行文件?它查找的第一个位置是当前目次。如果在那里找到,那就是执行的文件。否则,解释器将在path变量中定义的每个目次中依次查找它,并执行它找到的第一个目次。如果在这些目次中找不到具有此名称的可执行文件,解释器只会将errorlevel设置为9009。(希奇的是,如果call命令位于可执行文件的名称之前,则错误的返回码为1。)
让我们执行同一行代码,假设UartAssist.exe位于D:\Batch\08\中。如果这个目次是当前目次,程序将被找到并执行。否则,如果该目次位于path变量中,则可能会找到并执行该程序。假定该程序没有被位于path变量层次布局的当前目次或更高目次中的具有类似名称和扩展名的不同程序所取代。
如果这些都不为真,则无法找到程序,但是有不同的方法可以确保解释器找到可执行文件。首先,我们可以使用cd命令在执行程序之前更改当前目次:
  1. cd D:\Batch\08\
复制代码
大概,我们可以通过以下两种方式之一修改path变量以包含该目次。这里我在path前面加上前缀:
  1. path D:\Batch\08\;%path%
复制代码
这里我附加了path:
  1. path %path%;D:\Batch\08\
复制代码
如果附加了该目次,而且在path变量中先前定义的目次中存在另一个名为UartAssist.exe的文件,则将执行该程序。添加目次可确保我的可执行文件在其他任何文件之前被获取,但这并非没有其自身的伤害。它可能会在path变量中引入一些内容,这些内容将覆盖其他进程使用的资源。
这绝不是一个糟糕的技术;事实上,如果管理得当,它是非常有用的。使用当前目次或路径变量查找可执行文件的一个重要用途是使代码可移植。您可以将bat文件保存在单个文件夹中,也可以将其他bat文件以及任意数目的可执行文件、配置文件和其他资源保存在更复杂的文件夹布局中。然后,您可以将该文件夹复制到具有不同根目次布局的其他盘算机和网络。由于当前目次基本上遵循高级bat文件,因此如果使用当前目次查找其其他组件,它将在这些不同的位置工作。
您可以将默认的可执行文件放置在与bat文件类似的文件夹中。如果单独运行,它将使用这个可执行文件。如果从具有不同当前目次的另一个bat文件调用,它可能会找到一个不同的程序,答应其他人使用您的bat文件来调用他们自己的可执行文件。简而言之,您可以创建同名程序的层次布局,其中不同的程序在不同的实例中执行。
为了进一步阐明这一点,我在前面暗示过,调用程序甚至不必要扩展。也就是说,如果UartAssist.exe保存在当前目次中,它可能会被这行代码调用:UartAssist。
解释器通过另一个伪环境变量pathext查找没有扩展名的可执行文件,该伪环境变量包含以分号分隔的扩展的层次布局,就像path变量包含目次的层次布局一样。解释器仍然在当前目次中查找可执行文件,然后是path变量中的目次,但是在每个文件夹中,它现在查找它能找到的第一个具有UartAssist文件名和给定层次布局中列出的扩展名的可执行文件。
如果pathext变量没有被别人或其他东西修改过,那么它可能包含大约十几个文件扩展名,以.com、.exe、.bat和.cmd开头——按照这个序次。因此,唯一能制止前一个命令从当前目次执行UartAssist.exe的实体是当前目次下的UartAssist.com。(如果必须重置这个变量,请使用set命令。pathext变量只是一个变量,而不是命令。)
推送和弹出当前目次

cd命令在更改当前目次方面做得很好,但是之前的当前目次会丢失,再也不会知道了。通常这是完全可以的,但在其他环境下,您可能希望在将当前目次规复到从前的状态之前临时更改当前目次。也许一个实用程序bat文件被编写为可以从许多其他bat文件调用。在短时间内,我将讨论如何从一个bat文件调用另一个bat文件,但是现在,我们只必要理解被调用的bat文件的透视图。
被调用的bat文件可能在某个文件夹中创建或使用资源,因此在bat文件开始时更改当前目次是故意义的。但是,当被调用的bat文件完成并将控制转回调用的bat文件时,应该规复先前的当前目次。这很简单,因为调用bat文件可能在不同的目次中工作,更改其当前目次很可能会导致问题。一个更安全的操纵是,被调用的bat文件希望将其目次保留给自己。如果被调用的bat文件没有规复当前目次,则调用的bat文件可能会在当前目次中删除不必要的文件。被称为bat的文件可以隐藏它的目次,同时也体现得很有礼貌。
为相识决这个问题,可以在执行cd命令之前将先前的当前目次存储在一个变量中,然后可以在bat文件末尾执行另一个cd命令来设置它。但是批处理提供了两个命令,它们一起可以更优雅地完成这个任务,即pushd和popd命令。
pushd命令像cd命令一样更改当前目次,但它也将先前的当前目次推入堆栈以供以后使用。它有时被称为push目次命令,不外为了简洁起见,通常将其读成书写的样子,即“push-d”命令。在bat文件的开头,这个命令将简洁地执行这两个任务:
  1. pushd D:\Batch\08\
复制代码
在bat文件末尾或接近末尾时,以下简短命令将移动到D:\Batch\08\作为当前目次,并从堆栈中检索或弹出先前的当前目次,使用它来规复当前目次:popd。
这有时被称为弹出目次命令,但更常见的是“pop-d”命令。
注意这里没有参数;popd是很少接受任何参数的命令。当执行多个pushd命令时,每个命令都将另一个先前的当前目次推入堆栈,而且每个后续的popd命令将规复最近添加的目次。
同样值得注意的是,如果通报给pushd命令的参数是一个网络路径,则将未使用的最高驱动器号分配给该路径,而且popd命令将取消分配。末了,不带参数的pushd命令显示堆栈上目次的完备列表,从最近添加的目次开始。
警告:
push和popd命令的平衡非常重要。如果pushd分配了一个网络路径,那么相应的popd应该始终执行,纵然处理了错误。如果没有,任何映射的驱动器号将保持映射,纵然在bat文件完成之后。如果这种环境经常发生,盘算机将耗尽可用的驱动器号。
通过当前目次查找其他资源

当前目次的用途远不止于查找要执行的程序。对于任何资源(如文件),如果没有定义路径,则假定当前目次为其路径。比方,在前面文章中,这个命令删除了一个显式文件和所有以特定扩展名结尾的文件:
  1. del /Q D:\Batch\07\Source\Junk.txt D:\Batch\07\*.OLD
复制代码
如果当前目次是D:\Batch\07\Source\,这是从前一个命令中删除两次的路径,下面的命令用更少的按键执行类似的任务:
  1. del /Q Junk.txt *.OLD
复制代码
对于xcopy命令的源参数和接受路径和文件名作为参数的任何其他命令也是如此。我通常更喜欢使用显式路径来避免任何歧义,但这种技术为本文中形貌的大量命令提供了类似类型的机动性。再次思考前一篇文章,想象一下在没有明确路径的环境下复制、移动和重命名文件的所有命令。如果解释器在当前目次中找到一个或多个文件,那么它们都是很好的命令。
将参数通报给可执行文件

在本文的开头,我演示了如何调用编译后的程序。在继续之前,我要分享关于这个语法的末了一个观察结果。
可执行文件在执行时通常接受一个或多个参数。只需在程序反面列出这些形参,就可以将它们作为实参通报给程序。为了便于阅读,我将三个参数放入变量中:
  1. set inFile=D:\Batch\08\Input.dat
  2. set outFile=D:\Batch\08\Output.dat
  3. set logFile=D:\Batch\08\Log.dat
  4. %UartAssist% %inFile% %outFile% %logFile%
复制代码
输入文件是通报给程序的第一个参数;在许多语言中,这将被认为是程序中的args[0]。同样,输出文件是第二个参数,args[1],日志是第三个参数,args[2]。你也可以使用硬编码的值,参数可以是任何你喜欢的;它们不肯定是文件。
总结

执行编译后的程序一开始看起来很简单。毕竟,您甚至不必要命令。但是,如果不相识我在这里详细介绍的当前目次和path变量的细节,您就无法真正理解它是如何工作的。您已经相知趣识释器如何使用它们来查找可执行文件、文件和任何其他资源,以及管理这些重要变量内容的多种方法。
执行另一个bat文件与执行编译后的程序类似,但又不类似,我们将在反面的文章中相识这些区别。但在深入研究之前,您将在下一篇文章中相识标签及其许多重要用途,重要是它们对命令执行的时间和频率的影响。
本文由博客一文多发平台 OpenWrite 发布!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4