2015-11-02 91 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