繁体   English   中英

批处理:如何在变量中存储带有空格的命令输出?

[英]Batch: How to store command output with spaces in variable?

我想制作一个批处理文件来为可执行文件(例如,python)创建 Windows 防火墙规则。 为此,我有以下脚本:

REM ~ Open ports. Run with elevated administrator rights.
CALL :OPEN "python"
GOTO :EOF

:OPEN
IF ERRORLEVEL 1 (
  GOTO :EOF
)
FOR /F %%i IN ('where %1') DO CALL :OPEN_PROGRAM "%1" %%i && GOTO :EOF
GOTO :EOF

:OPEN_PROGRAM
FOR %%j IN (TCP UDP) DO CALL :OPEN_PROGRAM_PORT %1 %2 "%%j"
GOTO :EOF

:OPEN_PROGRAM_PORT
netsh advfirewall firewall add rule name=%1 description=%1 dir=in action=allow edge=deferuser     profile=private program=%2 protocol=%3
GOTO :EOF

只要可执行文件的路径中没有空格,就可以正常工作。

如果路径中有空格,则仅将空格之前的部分放入%%i变量中。 我尝试使用'where /F %1' ,但它仍然会削减空间上的输出。

有没有办法将where %1的完整输出存储在变量中? (最好不要将其写入文件)

我首先建议您不要传递没有扩展名的文件名。 这样做依赖于%PATHEXT%下列出的每个扩展名,您可以拥有名为python.compython.batpython.cmdpython.vbspython.vbepython.jspython.jsepython.wsfpython.wshpython.msc ,以及python.exe 我相信您不会在不知不觉中为所有这些创建防火墙规则。

我还建议您不要为此使用where命令。 原因是它可以返回多个项目。 例如,试试这个, where notepad.exe并且如果没记错的话,您可能会看到C:\\WINDOWS\\System32\\notepad.exe ,然后是C:\\WINDOWS\\notepad.exe 这是因为where.exe按列表顺序搜索%PATH%中的每个位置,并返回每个位置,因为%PATH%下的前两个条目默认应为C:\\WINDOWS\\system32;C:\\WINDOWS; .

因此,我的建议是使用另一种方法,它返回在%PATH%下找到的第一个项目,而不是所有项目,如果您正确使用了变量,这应该返回默认的(最常用的)项目。 方法是%~$PATH变量扩展,在for命令的帮助信息下有说明,即输入for /? 在命令提示符处。

示例脚本:

@Echo Off
SetLocal EnableExtensions
Rem ~ Open ports. Run with elevated administrator rights.
"%__AppDir__%reg.exe" Query HKU\S-1-5-19 1>NUL 2>&1 || (
 Echo This script must be run elevated.
 Echo Please use 'Run as administrator'
 "%__AppDir__%timeout.exe" /T 3 /NoBreak 1>NUL
 GoTo :EOF)
Call :OpenPorts "python.exe"
Pause
GoTo :EOF
 
:OpenPorts
For %%G In ("%~1") Do For %%H In (TCP UDP) Do (
 "%__AppDir__%netsh.exe" AdvFirewall Firewall Add Rule^
 Name="%~n1" Description="%~1" Dir=in Action=allow^
 Edge=deferuser Profile=private Program="%%~$Path:G"^
 Protocol=%%H)
Exit /B

我已经删除了所有不必要的Call命令, (只使用一个) ,并故意使用插入符号来分割你的超长行,以提高可读性; (这也允许您包含localport=和/或remoteport=选项,我假设您的“开放端口”名称是您稍后要作为对上述内容的修改而包含的) 我还冒昧地包含了一些代码,以确定脚本是否正在运行,如果不是,则在关闭之前显示一条消息。

where.exe的输出写入文件,然后一次读取一行。 有一种方法可以在“===”行之后没有临时文件。

@ECHO OFF
SET "XTOFIND=%~1"
SET "TEMPFILE=%TEMP%\wherelist.tmp"
IF EXIST "%TEMPFILE%" (DEL "%TEMPFILE%")

"%__appdir__%where.exe" "%XTOFIND%" >"%TEMPFILE%"

FOR /F "tokens=*" %%A IN ('TYPE "%TEMPFILE%"') DO (
    ECHO CALL :OPEN_PROGRAM "%%~A" %2 "%%J"
)

IF EXIST "%TEMPFILE%" (DEL "%TEMPFILE%")

ECHO ============

SET "XTOFIND=%~1"
FOR /F "tokens=*" %%A IN ('"%__appdir__%where.exe" "%XTOFIND%"') DO (
    ECHO %%~A
    ECHO CALL :OPEN_PROGRAM "%%~A" %2 "%%J"
)
EXIT /B 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM