为什么Powershell会被执行2到4次?

为什么Powershell会被执行2到4次?,powershell,batch-file,cmd,colors,Powershell,Batch File,Cmd,Colors,我正在为批处理制作API。它的一个功能是colortext,它使用PowerShell(如果机器上不支持PowerShell,则使用findstr)来完成工作。(它只需转换给定的批处理颜色,如3C,将其转换为PowerShell友好的名称,如DarkCyan和Red,并使用更多内容打印以颜色给出的文本。) 但是,当我尝试将前台设置为F(White)时,出于某种原因,它会尝试执行2到4次(取决于是否启用了延迟扩展) 如果假定的%fcn%和%bcn%从未应用,则在上次运行/尝试显示相同内容时,它有时

我正在为批处理制作API。它的一个功能是colortext,它使用PowerShell(如果机器上不支持PowerShell,则使用
findstr
)来完成工作。(它只需转换给定的批处理颜色,如
3C
,将其转换为PowerShell友好的名称,如
DarkCyan
Red
,并使用更多内容打印以颜色给出的文本。)

但是,当我尝试将前台设置为
F
White
)时,出于某种原因,它会尝试执行2到4次(取决于是否启用了延迟扩展)

如果假定的
%fcn%
%bcn%
从未应用,则在上次运行/尝试显示相同内容时,它有时会失败。(这还取决于是否启用了延迟扩展)

我只想让它执行一次(并且不会因为任何原因而失败),但是由于某种原因它执行了2到4次。我将如何执行/修复此程序

假设
%bcn%
%fcn%
%text%
已经设置好(假设
青色
%bcn%
白色
%fcn%
不应发生
%text%
):

其输出为:

如果我使用相同的文本制作一种颜色(如
CD
):

编辑:因为似乎没有人说“嘿,它工作得很好”,我的意思是关于第二次假处决,我知道这很好,我只是想摆脱假第二次处决

以下是批处理文件的完整代码(将其另存为bapi.bat并尝试运行“bapi colortext”,这不应在“BF”中运行):


发布的批次代码和环境变量值无法再现问题

不过,他在评论中也提出了部分建议

1.删除单个文件 单个文件的删除可以通过以下两种方式完成:

if exist colortest.ps1 del colortest.ps1
或与

del colortest.ps1 2>nul
第一个命令行首先检查要删除的文件是否存在,并且仅当文件确实存在时才运行命令DEL

第二个命令行运行命令DEL,并将写入处理STDERR的错误消息重定向到设备NUL,以抑制该错误消息。如果要删除的文件根本不存在,命令DEL将输出错误消息

IF之后或在FOR循环中运行单个命令时,实际上没有必要将此命令行写入定义命令块的圆括号中适用于,如果设计用于执行单个命令,并使用定义命令块的
,则它只是Windows命令处理器的一个扩展,能够在设计需要单个命令时运行多个命令

2.重定向到文件并覆盖现有文件 这里可以使用
>
而不是
>
来创建或覆盖
colortest.ps1
。这样就避免了在删除之前单独删除文件的需要

另请参阅Microsoft文章

3.输出文本和重定向运算符之间的空格字符 在命令行上

echo %script% >> colortest.ps1
环境变量引用
%script%
和重定向运算符
>
之间有一个空格字符。此空格字符也通过命令ECHO输出,因此也作为尾随空格写入文件

这在这里并不重要,但在生成的文件中通常不需要尾随空格。一种解决方案是删除空格字符并使用:

echo %script%>> colortest.ps1
但是,如果环境变量字符串
script
以空格和1到9范围内的一位数字结尾,这可能会导致意外行为,因为在
1>>colortest.ps1
2>>colortest.ps1
中执行之前预处理此命令行会导致此结果。。。这是将句柄1到9重定向到文件
colortest.ps1
,而不是将
1
打印到
9
以处理STDOUT并最终打印到文件

解决方案是首先写入重定向,然后写入命令

>>colortest.ps1 echo %script%
或者使用延迟扩展,在脚本PowerShell脚本行包含特殊字符的情况下,这种扩展会更好

echo !script!>>colortest.ps1
Windows命令解释器将忽略
>
和文件名
colortest.ps1
之间的空格字符

4.使用特殊字符引用参数字符串 环境变量
text
可能包含一个文本,该文本需要双引号引用此参数字符串,以便由Windows命令解释器和PowerShell进行正确处理。空格字符(命令行上的分隔符)和字符
&()[]{}^=;!'+`~|要求经常将整个参数字符串括在双引号中,以便完全解释为文字文本

set "script=write-host "!text!" -ForegroundColor %fcn% -BackgroundColor %bcn%"
另请参见关于为什么使用
set“script=script line”
而不是仅使用
set script=script line
的答案,以及为什么在将脚本行指定给环境变量时,脚本行中指定了多少双引号并不重要

5.要在PowerShell脚本文件中以文本形式输出的双引号 要通过PowerShell脚本输出包含一个或多个双引号的
文本
,在将
文本
字符串写入脚本文件
colortest.ps1
之前,必须使用一个或多个
对每个双引号字符进行转义

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "bcn=Cyan"
set "fcn=White"
set "text="This should not happen^^!""
set "text=!text:"=""!"
set "script=write-host "!text!" -ForegroundColor %fcn% -BackgroundColor %bcn%"
echo !script!>colortest.ps1
echo on
@powershell -executionpolicy remotesigned -file colortest.ps1
@echo off
endlocal
在本例中可以看出,如果在
文本的定义上启用了延迟扩展,则除了要输出两个双引号外,字符串还包含一个感叹号作为字符输出,感叹号必须转义
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "bcn=Cyan"
set "fcn=White"
set "text="This should not happen^^!""
set "text=!text:"=""!"
set "script=write-host "!text!" -ForegroundColor %fcn% -BackgroundColor %bcn%"
echo !script!>colortest.ps1
echo on
@powershell -executionpolicy remotesigned -file colortest.ps1
@echo off
endlocal
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "text="This should not happen!""
setlocal EnableDelayedExpansion
set "bcn=Cyan"
set "fcn=White"
set "text=!text:"=""!"
set "script=write-host "!text!" -ForegroundColor %fcn% -BackgroundColor %bcn%"
echo !script!>colortest.ps1
endlocal
echo on
@powershell -executionpolicy remotesigned -file colortest.ps1
@echo off
endlocal