我的问题与this问题有关。我有几个需要从批处理文件执行的操作,我想将它们建模为函数并从主序列调用。从上面的问题可以清楚地看到,我可以使用调用语法来完成此操作
call:myDosFunc
我的问题是,我能不能把所有这些函数放在一个单独的批处理文件(functions.bat)中,然后以某种方式“包含”到主批处理文件中并调用它们?另一种选择是利用调用语法从main.bat调用functions.bat的可能性,但我不确定我是否能用一个特定的函数来调用它,而不是执行整个批处理文件。
简而言之,我正在寻找类似于C编程世界的东西,在C编程世界中,我的函数驻留在DLL中,主程序只包含高级逻辑,并从DLL调用函数。
6条答案
按热度按时间gkn4icbw1#
我认为在批处理文件的开头使用路由函数并不是那么难看。您可以在"libbatch.cmd"的开头使用类似这样的函数
现在,您可以使用以下命令从另一个批处理调用func2:
这也保留了func2 "抛出"的错误级别(exit/b移交当前错误级别)。使用第二个调用而不是goto,您可以确保"%1"=="param1"而不是func2。如果标签不存在,调用不会终止批处理文件,它只是将错误级别设置为1,并将错误消息放置为2(errorout),这可能会被重定向为nul。
说明:%* 包含所有参数,因此在示例中,第一行转换为:
jfewjypa2#
这里有一个简单的例子来说明如何做到这一点。
调用函数脚本时,函数名作为第一个参数,函数参数为arg 2、arg 3...
假设函数被正确调用,脚本会将参数移位并执行后藤操作到原始的arg 1。然后函数的参数会从新的arg 1开始。这意味着您可以使用已经编写好的例程并将它们放入实用程序中,而不必担心调整参数编号。
如果未提供函数参数,或者函数参数与脚本中的有效标签不匹配,则脚本将给出错误。
我更喜欢上面使用的后藤方法,另一种选择是使用CALL,就像托马斯在他的回答中所做的那样。
有关使用CALL技术的实用批处理函数库的工作示例,请参见CHARLIB.BAT,这是一个用于处理批处理文件中的字符和字符串的例程库。here中提供了一个显示库开发的线程
我几年前写过CharLib.bat,如果我今天写它,我可能会用后藤而不是CALL。
引入CALL的问题是,当将字符串常量作为参数传递时,它会产生问题。额外的CALL意味着包含
%
的字符串常量必须额外地将百分比加倍。它还意味着需要额外地转义未加引号的有害字符,如&
和|
。这两个问题可以由调用者解决。但真实的的问题是,每个CALL都会使引号中的插入符号加倍:"^"
变为"^^"
。没有解决插入符号加倍问题的好方法。额外CALL的问题不会影响CharLib.bat,因为字符串值是通过引用(变量名)传递的,而不是作为字符串常量。
使用带有SHIFT /1的后藤的唯一缺点是不能使用
%0
来获取当前正在执行的例程的名称。我可以使用不带/1的SHIFT,但是这样就不能在例程中使用%~f0
来获取正在执行的批处理文件的完整路径。pxq42qpu3#
您可以使用此格式-并像这样启动它:
这将是使用库的一种方式
omqzjyyz4#
你可以使用一个有趣的技巧来避免其他方法在试图使库函数对主程序可用时所遇到的大多数问题,而且它要快得多。使用这个技巧的唯一必要条件是:
诀窍在于 “切换上下文” 的运行批处理文件的方式,库文件成为运行批处理文件;这样,库文件中的所有函数都可以在主代码块中使用,而不需要额外的处理。2当然,运行批处理文件的“上下文”必须在代码块结束之前切换回主文件。
“切换上下文”的方法是将库文件重命名为与正在运行的主文件相同的名称(并将主文件重命名为另一个名称)。例如:
EDIT:* 添加了工作示例 *
我从屏幕上复制了下面的例子。在Windows 8中测试过,但我也在Win XP中使用过这个方法:
t30tvxxf5#
我不确定原始问题的上下文,但这可能是一个切换到类似WSH与VBScript或WPS,或任何其他控制台能力的脚本而不是批处理文件的情况。我将回答原始问题,但首先..一点背景知识和理解..
DOS和Windows的命令行/控制台模式通常是COMMAND.COM或CMD.EXE,这并不适合脚本/编程逻辑。相反,它们适合执行命令和程序,批处理文件被添加到常用的命令序列中,以 Package 在一个单一类型的命令中。例如,您可能有一个旧的DOS游戏,每次都需要以下命令:所以它被打包成一个批处理文件
许多人倾向于将整个批处理文件视为一个原子单元--但事实并非如此。(COMMAND.COM或CMD.EXE)的作用就像是每次运行批处理文件时一行一行地手动键入这些行。它确实没有像常规编程/脚本语言那样的词汇和作用域的坚实概念--也就是说,它没有像调用堆栈那样维护很多额外的元数据,它所维护的一点东西更多的是像是事后的想法而不是从一开始就内置到批处理文件中。
然而,一旦您改变了思路,您通常可以使用各种技巧和技术来模拟更强大的脚本/编程语言,从而克服这个限制;但是您仍然必须记住,无论如何,批处理文件仍然是有限的。
无论如何,使用批处理文件库的一种技术是创建一个批处理文件,其中第一个参数用于指示正在调用哪个函数:
如果在编写库时考虑到这一点,那么它就能很好地工作,因此它会知道跳过第一个参数,等等。
在Windows系统中使用更现代版本的CMD.EXE允许在CALL语法中使用“:labels”,如果您想限制参数范围(例如,允许您使用%* 表示“所有参数”),这会很有用,如下所示:
(from在同一批处理文件中或...)
在第一种形式中,:LABEL必须已经在当前批处理文件中。它将在CMD.EXE中创建一个新的“批处理上下文”,其中%*、%1、%2等与参数匹配。但是您还必须提供某种返回/退出逻辑,以便从该上下文返回/退出到调用上下文。
在第二种形式中,CMD.EXE并不能真正识别您正在传递给它的标签,因此您的批处理文件库必须预期并处理它:
这是因为命令解释器在解析CALL命令之前就替换了%,所以在变量扩展之后,CALL命令会看到:LABEL,就好像它是硬编码的一样。这也会造成CMD.EXE创建另一个批处理上下文的情况,所以你必须确保从那个上下文返回/退出两次:一次用于当前的库上下文,再次用于返回到原始CALL。
还有其他的方法来做一个批处理文件库,混合和匹配上述技术,或者使用更复杂的逻辑,使用后藤的,等等.这实际上是一个如此复杂的主题,有整个章节的书籍写的主题,远远超过我想在这里输入一个简单的答案!
到目前为止,我基本上忽略了您将遇到的其他问题:如果CALL标签不存在怎么办?如何处理?环境变量扩展怎么办?什么时候发生?如何防止它过早发生?在参数/参数中使用特殊DOS字符怎么办?例如,解释器如何看到这样的行:CALL:ProcessPath %PATH%?(答案是CMD.EXE*在处理CALL命令之前替换整个%PATH%**。如果您的路径中有空格,这可能会导致问题,这可能会影响CALL处理整个过程的方式,就像许多Windows的%PATH%变量一样.. C:\Program Files..例如..)
正如你所看到的,事情很快就变得复杂和混乱。你必须停止像程序员那样思考,而开始像COMMAND.COM/CMD.EXE那样思考,它几乎一次只看到一行,而不是整个批处理文件作为一个原子单元。事实上,这里有一个例子可以帮助你真正掌握它的工作方式。
创建一个文件夹C:\testing,并将下面的批处理文件“oops.bat”放入其中:
现在打开一个控制台窗口并运行它,但是让它在PAUSE时保持不变:
当它处于PAUSE状态时,在文本编辑器中打开oops.bat并将其更改为:
保存它,然后切换回控制台窗口,按任意键继续运行批处理文件:
哇...看到那个错误了吗?那是因为我们在批处理文件还在被CMD.EXE运行的时候编辑了它,但是我们的编辑改变了批处理文件CMD.COM认为它在的地方。在内部,CMD.EXE维护了一个文件指针,指示要处理的下一个字符的开始,在本例中,它应该是PAUSE行后面的字节(和CRLF)。但是当我们编辑它的时候,它改变了批处理文件中下一个命令的位置,但是CMD.EXE的指针仍然在同一个地方。在这个例子中,它指向“ECHO Oops!”行中间的字节位置,因此它尝试在PAUSE之后将“ops!”作为命令处理。
我希望这能清楚地表明COMMAND.COM/CMD.EXE总是将批处理文件看作字节流,而不是像脚本语言或编译器那样将其看作逻辑块、子例程等。这就是为什么批处理文件库如此有限的原因。它使得不可能将库“导入”到当前运行的批处理文件中。
哦,我刚刚有另一个想法..在现代Windows的CMD.EXE,你总是可以创建一个批处理文件,创建一个 * 临时 * 批处理文件的飞行,然后调用它:
这实际上在临时目录中创建了一个临时批处理文件,名为TMP####.BAT(其中#被替换为随机数; %RANDOM:~ 0,1%表示取%RANDOM%返回的数字的第一位--这里我们只需要一个个位数,而不是RANDOM返回的完整数字..),然后ECHO的“Hello,World”,后面跟着它自己的全名(%~ dpnx 0部分),CALL临时批处理文件,然后依次是ECHO的“Hi Mom!”,后面跟着它自己的[random]名称,然后返回到原始批处理文件,以便它可以执行任何需要的清理操作,例如在本例中删除临时批处理文件。
无论如何,从这篇文章的长度可以看出,这个主题并不简单,网上有很多网页提供了大量的批处理文件技巧、窍门等等,其中很多都深入到如何使用它们,创建批处理文件库,注意什么,如何通过引用与通过值传递参数,如何管理变量展开的时间和位置等等。
在谷歌上快速搜索“批处理文件编程”,找到其中的许多,你也可以查看Wiki和WikiBook,SS64.comrobvanderwoude.com,甚至DMOZ's directory,了解更多的资源。
祝你好运!
0x6upsns6#
下面是一个cmd批处理脚本,它将文件或文件夹中的文件**(递归) 导入主脚本:
使用方法:
import.cmd
/install
标志调用它以便安装它(不需要管理员)要了解如何使用它,只需使用
/?
标志调用它。