2015-11-02 118 views
0

我有很大的遺留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,所以我認爲這是不依賴於操作系統的。

回答

3

看起來像cmd的錯誤。讓我們有這個Test.cmd文件:

@(
    exit /b 1 
    rem 
) 

現在,在命令行中鍵入以下命令:

> Test.cmd 

> echo %errorlevel% 
1 

> cmd /c Test.cmd 

> echo %errorlevel% 
0 

正如你所看到的,誤差水平不正常,如果你運行.cmd文件中設置子shell。

+0

好點,我錯過了'call'實際上並沒有調用subshel​​l的事實。 – n0rd