使用带有双引号的参数时,批处理脚本出现问题

3

我写了以下脚本,它会要求用户输入密码作为参数。如果我输入密码"Hello&123",它会失败,但是对于其他情况,如!Hello&123>,它可以正常工作。请建议一些好的方法来克服这种情况。

TestScript1.bat

@echo off
setlocal

set "psCommand=powershell -Command "$pword = read-host 'Enter password:' -AsSecureString ; ^
      $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
            [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set password=%%p
if "%password%" == "" @echo password cannot be empty & goto DIE
TestScript2.bat.bat testuser "192.168.1.1" "%password%"
endlocal

:DIE
exit /b 1

TestScript2.bat

@echo off

echo n | psftp %1@%2 -pw %3 -b Test3.bat >> TestLog.log 2>&1
3个回答

1
当您尝试展开变量时,需要使用延迟扩展。
延迟扩展对于任何内容都是安全的。
但是,使用延迟扩展会遇到感叹号和脱字符的问题。
这就是为什么您应该在set "password=%%p"之后启用它的原因。
@echo off
setlocal DisableDelayedExpansion
set "psCommand=powershell -Command "$pword = read-host 'Enter password:' -AsSecureString ; ^
      $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
            $str=[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR); ^
            Write-host('#'+$str)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set "password=%%p"
setlocal EnableDelayedExpansion
set "password=!password:*#=!"
if not defined password (

    echo password cannot be empty
    goto :DIE
)
echo It works: pwd=!password!
TestScript2.bat testuser "192.168.1.1" "!password!"

但是您将在TestScript2.bat中遇到下一个问题,因为扩展本身是安全的,但您无法通过值将任意密码传递给函数或批处理文件(这确实是不可能的)。因此,您应该通过引用而不是值来传递它。
TestScript2.bat testuser "192.168.1.1" password

接下来在TestScript2.bat中再次使用!%~3!

但是,使用密码调用psftp命令会导致任意值的问题。
您需要将内容转义为安全格式,在这种情况下,您必须考虑psftp的规则。
我测试过了,psftp将\""替换为"

TestScript2.bat

@echo off
setlocal EnableDelayedExpansion
set "password=!%~3!"
set "password=!password:"=\""!"
... more replace rules
echo n | psftp %1@%2 -pw "!password!" -b Test3.bat >> TestLog.log 2>&1

谢谢你的回答,但是它对于密码“Hello&123”失败了。在这个密码中,我们有三个特殊字符,两个双引号和一个 &。 - Aryan
我们需要在其他脚本中添加 setlocal EnableDelayedExpansion 吗? - Aryan
是的和不是的,它从TestScript1.bat继承状态,但为了编写一个好的脚本,您应该显式启用它。但即使这样也不起作用,因为在psftp -pw !%3!部分仍然会失败,因为您会再次遇到无法按值传输任意内容的问题。 - jeb
是的,我遇到了同样的问题。有什么办法可以克服这个问题吗?只有当密码包含特殊字符时才会失败。 - Aryan
因此,我添加了示例TestScript2.bat - jeb
显示剩余5条评论

0

我认为你想要的是这样的:

SET Test="Hello"
FOR /F "TOKENS=2 DELIMS==" %a in ('SET Test') DO @ECHO %~a

%~a会去掉任何引号。


不是说我想在密码中保留双引号。如果我们从密码中删除双引号,那么密码将是错误的,并且无法连接到主机,会显示访问被拒绝。 - Aryan
问题通常是字符串中引号数量错误。您说未加引号的密码可用,但加上引号后就不行了。因此,如果您使用以上内容为基础,可以删除所有引号,然后只添加一对。此外,您还需要检查密码中是否含有"和<>,因为这些符号会破坏某些东西。另外,TestScript2.bat.bat也不正确。 - Code Gorilla
这里的问题是密码包含双引号,这会导致失败,如果密码包含除“双引号”以外的其他特殊字符,则可以正常工作。 - Aryan
1
当允许使用引号时,您不能从密码中删除引号。而且 %~ 只会去掉外部的引号,如果字符串本身包含引号,它将无法正常工作,例如 This is "&"& hard - jeb
是的,您需要其他方法来剥离内部引号,但我认为密码应该带有引号。 - Code Gorilla
示例密码 = "HiMatt&Stack",因此此密码共有14个字符,包括两个双引号。 - Aryan

0

在编程中,&符号和>都需要进行转义(!Hello^&123^>),因为它们目前没有被转义。如果收到%3,则会被解释为!Hello

您可以使用延迟扩展来解决这个问题:

setlocal enableDelayedExpansion
TestScript2.bat testuser "192.168.1.1" !password!

只有当密码为"Hello&123"时才会出现此问题,但对于<Hello&123>则不会。因此,如果密码包含"符号,则会失败,否则将通过。 - Aryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接