我有很大的遺留cmd腳本,用作我們使用的某些軟件的設置的一部分。腳本從cmd和powershell腳本中調用。有時會失敗,這是由退出代碼表示的。該腳本的問題是它創建了很多環境變量,並且不能很好地處理它們,所以如果在同一環境中運行兩次,第二次執行可能無法按預期工作。只有從cmd
運行時纔會出現問題,Powershell總是在子shell中啓動cmd腳本,所以在那裏不是問題。現在powershell指示的錯誤退出代碼
,我快,迫使它在子shell運行修復它(所以當腳本終止,子shell被終止,也和我們在一個乾淨的環境準備再次運行腳本結束)。 「Fix」看起來像這樣:
@echo off
if "%running_in_subshell%"=="" (
set running_in_subshell=1
cmd /c %0
if errorlevel 1 (
set running_in_subshell=
echo fail
exit /b 1
) else (
set running_in_subshell=
echo success
exit /b 0
)
goto :eof
)
rem lot of weird old code noone wants to touch here, now run in a subshell
echo exiting with error, subshell: %running_in_subshell%
rem it does not always exits with "1", but for the sake of this question let return error always
exit 1
有趣的部分現在開始。修復完成後,調用它的Powershell腳本開始遇到檢測失敗的問題。假設,我們將上面的腳本保存爲a.cmd
。 CMD腳本:
@echo off
call a.cmd
if errorlevel 1 (
echo ^>^> script failed
) else (
echo ^>^> script succeeded
)
產生以下輸出:
exiting with error, subshell: 1
fail
>> script failed
其被預期,但的powershell腳本:
.\a.cmd
if ($lastexitcode -gt 0)
{
write-output ">> script failed"
}
else
{
write-output ">> script succeeded"
}
產生
exiting with error, subshell: 1
fail
>> script succeeded
WAT ???現在更有趣的部分:如果我從原始腳本中刪除goto :eof
,它會開始按預期工作(經過一些調試後,我意外地將它留在那裏)。但它甚至不應該作爲退出腳本之前的if
的兩個分支來執行。我錯過了什麼?爲什麼我看到我所看到的?
我目前使用的是Windows 10,但我看到在Windows Server 2012上相同的行爲,在Windows Server 2012 R2和Windows 8,所以我認爲這是不依賴於操作系統的。
好點,我錯過了'call'實際上並沒有調用subshell的事實。 – n0rd