我需要在运行批处理文件时传递一个ID和密码,而不是将它们硬编码到文件中。

下面是命令行的样子:

test.cmd admin P@55w0rd > test-log.txt

当前回答

如果你担心安全/密码盗窃(导致你设计这个解决方案,需要登录凭证在执行而不是静态的硬编码不需要数据库),然后您可以存储api或一半密码解密的代码或程序文件解密密钥,所以在运行时,用户将在控制台输入用户名/密码散列/解密之前传递给程序代码执行通过设置/ p,如果你查看在运行时用户输入凭据。

如果您正在运行一个脚本,使用不同的用户/密码运行程序,那么命令行参数将适合您。

如果您正在制作一个测试文件来查看不同登录的输出/效果,那么您可以将所有登录存储在一个加密文件中,作为参数传递给test。Cmd,除非你想坐在命令行并输入所有的登录,直到完成。

可以提供的参数数量限制为命令行上的字符总数。为了克服这一限制,上一段技巧是一种变通方法,不会有暴露用户密码的风险。

其他回答

对于使用循环获取所有参数并纯批处理:

注意事项:用于不带:?*&|<>


@echo off && setlocal EnableDelayedExpansion

 for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && (
     call set "_arg_[!_cnt!]=!_arg_!" && for /l %%l in (!_cnt! 1 !_cnt!
     )do echo/ The argument n:%%l is: !_arg_[%%l]!
 )

goto :eof 

你的代码已经准备好在需要的地方用参数号做一些事情,比如……

 @echo off && setlocal EnableDelayedExpansion

 for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"
 
 fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
 

另一个有用的技巧是使用%*表示“所有”。例如:

echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*

跑步时:

test-command admin password foo bar

上面的批处理文件将运行:

fake-command /u admin /p password admin password foo bar

我的语法可能有点错误,但这是大意。

受到@Jon在其他地方的回答的启发,我设计了一个更通用的算法来提取命名参数、可选值和开关。

假设我们想要实现一个实用程序foobar。它需要一个初始命令。它有一个可选参数——foo,它接受一个可选值(当然不能是另一个参数);如果缺少该值,则默认为default。它还有一个可选参数——bar,它接受一个必需的值。最后,它可以带一个标志——baz,不允许有任何值。哦,这些参数可以以任何顺序出现。

换句话说,它看起来像这样:

foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]

这里有一个解决方案:

@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson

SET CMD=%~1

IF "%CMD%" == "" (
  GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=

SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
  SHIFT
  IF NOT "%ARG%" == "" (
    IF NOT "%ARG:~0,2%" == "--" (
      SET FOO=%ARG%
      SHIFT
    ) ELSE (
      SET FOO=%DEFAULT_FOO%
    )
  ) ELSE (
    SET FOO=%DEFAULT_FOO%
  )
) ELSE IF "%PARAM%" == "--bar" (
  SHIFT
  IF NOT "%ARG%" == "" (
    SET BAR=%ARG%
    SHIFT
  ) ELSE (
    ECHO Missing bar value. 1>&2
    ECHO:
    GOTO usage
  )
) ELSE IF "%PARAM%" == "--baz" (
  SHIFT
  SET BAZ=true
) ELSE IF "%PARAM%" == "" (
  GOTO endargs
) ELSE (
  ECHO Unrecognized option %1. 1>&2
  ECHO:
  GOTO usage
)
GOTO args
:endargs

ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
  ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
  ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
  ECHO Baz
)

REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof

:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1

使用SETLOCAL,这样变量就不会转义到调用环境。 不要忘记初始化变量SET FOO=等,以防有人在调用环境中定义了它们。 使用%~1删除引号。 使用IF "%ARG%" == "",而不是IF [%ARG%] ==[],因为[和]不会使用以空格结尾的值。 即使你在if块内SHIFT,当前的参数如%~1也不会被更新,因为它们是在解析if时确定的。您可以在IF块中使用%~1和%~2,但这将令人困惑,因为您有一个SHIFT。你可以把SHIFT放在块的末尾,但这可能会丢失和/或混淆人们。所以“捕获”块外的%~1和%~1似乎是最好的。 你不想用一个参数来代替另一个参数的可选值,所以你必须检查IF NOT "%ARG:~0,2%" == "——"。 当您使用其中一个参数时,请注意只使用SHIFT。 重复的代码SET FOO=%DEFAULT_FOO%是令人遗憾的,但另一种选择是在IF NOT "%ARG%" == ""块之外添加一个IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%。然而,因为它仍然在IF "%PARAM%" == "——foo"块中,% foo %的值将在你进入块之前被计算和设置,所以你永远不会检测到——foo参数存在,而且% foo %的值缺失。 注意ECHO缺失条值。1>&2向stderr发送错误消息。 想在Windows批处理文件中使用空行?你必须使用ECHO:或其中一种变体。

访问批处理参数可以简单地使用%1,%2,…%9或%*, 但前提是内容简单。

对于像“&”^&这样的复杂内容,没有简单的方法,因为不可能访问%1而不产生错误。

set  var=%1
set "var=%1"
set  var=%~1
set "var=%~1"

这些线延伸到

set  var="&"&
set "var="&"&"
set  var="&"&
set "var="&"&"

并且每一行都失败,因为其中一个&在引号之外。

这可以通过从临时文件中读取参数的注释版本来解决。

@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
    set "prompt="
    echo on
    for %%b in (1) do rem * #%1#
    @echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
  set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

诀窍是在rem语句后启用echo并展开%1(也适用于%2 ..% *)。 因此,即使是“&”&也可以被重复而不会产生错误,正如上面所说的那样。

但是为了能够重定向echo on的输出,您需要两个for循环。

额外的字符* #用于安全对抗/?(有助于快速眼动)。 或者行尾的插入号可以作为多行字符,甚至在rem之后。

然后从文件中读取rem参数输出,但要小心。 FOR /F应该在延迟展开关闭的情况下工作,否则带有"!"的内容将被销毁。 在删除param1中的额外字符后,您就得到了它。

要以安全的方式使用param1,请启用延迟扩展。

我是这样做的:

@fake-command /u %1 /p %2

下面是命令的样子:

test.cmd admin P@55w0rd > test-log.txt

%1应用于第一个参数,%2(这是棘手的部分)应用于第二个参数。您最多可以通过这种方式传递9个参数。