从 bat 文件创建 Android 密钥库

Create a Android keystore from a bat file

我写了一个bat文件通过keytool生成一个keystore。 我的代码是:

cd C:\Java\jdk-11.0.1\bin

set Pass=12345678
set RepetitionPass=test
set FLname=test
set OrganUnit=test
set Organ=test
set City=test
set State=test
set Country=US

set Pass=%Pass: =%
set RepetitionPass=%RepetitionPass: =%
set FLname=%FLname: =%
set OrganUnit=%OrganUnit: =%
set Organ=%Organ: =%
set City=%City: =%
set State=%State: =%
set Pass=%Pass: =%
set Country=%Country: =%

(echo.%Pass% && echo.%RepetitionPass% && echo.%FLname% && echo.%OrganUnit% && echo.%Organ% && echo.%City% && echo.%State% && echo.%Country% && echo y)| keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
pause

我将这段代码放在记事本中,然后将其扩展名更改为.bat。 一切正常 我唯一的问题是自动添加了 space 密码的末尾。比如我的密码是“12345678”,生成密钥时,它的密码就是“12345678”。 出于某种原因,我不想使用 Android Studio 生成密钥,我必须以这种方式生成我的密钥库。 问题出在哪里?我该如何解决这个问题?

Windows命令提示符对SPACEs相当敏感,所以当你提供这样的命令时,它们可能会产生一些影响。例如:echo foo & echo bar 将输出一行 foo + SPACE 和一行 bar (假设没有“隐形”尾随 SPACE,当然)。

但手头的情况更复杂:你的批处理脚本中有一个管道 (|),它将为左侧启动一个新的 cmd.exe 实例,因为那里是一个带括号的块1;这个新实例接收到以某种方式重建的左侧代码,因此插入了更多不需要的 SPACEs 。回到前面的例子,(echo foo&echo bar) | more 会 return 甚至两行尾随 SPACE each2 ,因为左边的命令将被重建为 ( echo foo & echo bar ).

即使是以下内容,每行仍会 return 尾随 SPACE

(
    echo foo
    echo bar
) | more

因为左侧的命令方块将再次重建为 ( echo foo & echo bar )


一个可能的解决方案是 escape 符号,这样它就可以直接传递给新的 cmd.exe 实例而无需修改:

(echo foo^& echo bar) | more

显然这只会阻止第一行附加 SPACE,但是当我们附加另一个转义的符号加上一个实际上什么都不做的命令时,比如 rem/3,求解完毕:

(echo foo^& echo bar^& rem/) | more

块方法同样适用:

(
    echo foo^& rem/
    echo bar^& rem/
) | more

最终会翻译成 ( echo foo& rem/ & echo bar& rem/ ).


现在让我们将其应用到您的代码中,并进行其他一些更改:

  • cd command requires the /D option in order to change the current drive as well, and quoting paths is generally a good practice. Also consider what to do when the path does not exist or cannot be accessed for some reason (conditional execution && or || 可以在这里服务。
  • 您通常应该更喜欢 set command 的引用语法,例如 set "Pass=12345678" 而不是 set Pass=12345678,以保护特殊字符并避免不需要的尾随 SPACEs.
  • 我完全跳过了删除 SPACEs 的代码块,因为我认为这只是删除不需要的 [ 的失败尝试=127=]s 在输出中(如果你确实想要那个块,你应该使用像 set "Pass=%Pass: =%" 而不是 set Pass=%Pass: =% 这样的引用语法)。
  • 虽然被广泛使用,但 echo. 是回显(可能)空行的一种糟糕方式,因为在内部命令 echo 执行之前实际上搜索了名为 echo. 的文件.如果出于某种原因存在这样的文件,则会尝试执行该文件。因此,使用语法 echo(,看起来很奇怪但很安全。
  • 您不需要条件执行来链接 echo 命令,无条件的 & 运算符就可以了。

所以这里是可能固定的代码:

@echo off
cd /D "C:\Java\jdk-11.0.1\bin" || exit /B

set "Pass=12345678"
set "RepetitionPass=test"
set "FLname=test"
set "OrganUnit=test"
set "Organ=test"
set "City=test"
set "State=test"
set "Country=US"

(
    echo(%Pass%^& rem/
    echo(%RepetitionPass%^& rem/
    echo(%FLname%^& rem/
    echo(%OrganUnit%^& rem/
    echo(%Organ%^& rem/
    echo(%City%^& rem/
    echo(%State%^& rem/
    echo(%Country%^& rem/
    echo y^& rem/
) | keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
pause

1) 详细解释参考这个post: How does the Windows Command Interpreter (CMD.EXE) parse scripts? (see phase 5.3)
2) 使用output redirection (>)将输出写入文件以证明它。
3) 必须是 rem/ 而不是 rem,因为后者会注释掉命令行的全部剩余部分。