簡體   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