我有一个命令行,该命令行由第三方可执行文件(Intune管理扩展)调用。不幸的是,该可执行文件更喜欢在执行之前在命令行中扩展环境变量。此外,它在执行此扩展之前不会加载系统环境变量。
因此,如果我在命令行中放置了类似的内容,它将无法解决任何问题:
cmd /s /c "echo profile is: %userprofile%"
profile is:
我发现我可以通过如下使用延迟扩展来解决此问题:
cmd /s /v /c "echo profile is: !userprofile!"
但是,在我的真实情况下,这会分解为以下情况:
cmd /s /v /c "cmd /s /v /c "cmd /s /v /c "echo hello" > !userprofile!\tst.log""
The system cannot find the path specified.
但是,奇怪的是,这有效:
cmd /s /v /c "cmd /s /v /c "echo hello" > !userprofile!\tst.log"
有人可以向我解释为什么附加的嵌套级别可以打破这一点?
此问题的另一种可接受的答案:我如何才能采用任意有效命令行序列,将它们安全地组合到一个单行命令链中(使用&&),并将所有这些命令的输出重定向到输出日志文件?请记住,我在这里的局限性是这是第三方软件,并且能够执行single命令行。
一个真实的例子-我有3个命令:
安装某些软件:powershell .\Install.ps1
记录是否已成功安装软件:reg add "HKEY_CURRENT_USER\SOFTWARE\Foo\bar" /v "Installed" /d "%date:~4% %time%" /f /reg:64 > nul
输出到用户配置文件目录中的日志文件:>> %userprofile%\tst.log
如何将其组合成一个命令行?
现在,我有
cmd /s /c "cmd /s /c "cmd /s /c "powershell .\Install.ps1" && reg add "HKEY_CURRENT_USER\SOFTWARE\Foo\bar" /v "Installed" /d "%date:~4% %time%" /f /reg:64 > nul" >> "%userprofile%\install.log" 2>&1"
此方法有效,但%userprofile%的早期扩展除外...
[注意-如果我的外部命令重定向输出(>>
),则正在执行的第三方软件会崩溃,因此需要额外的包装层...
[命令行中的特殊字符是%
,&
,>
和!
。其中某些字符可能需要转义以延迟其使用。如果存在于字符串中,即">"
,则可以使它们成为文字,或者如果cmd
从命令行中删除周围的""
,则一旦它们不再是字符串的一部分,就可以延迟其特殊操作。
如果需要,可以通过加倍或更多倍来逃脱%
,即%%
。如果需要,可以使用脱字符号&
对>
,!
和^
进行转义。 %
和!
在字符串中可以保持特殊。查看关于Escape Characters, Delimiters and Quotes at the Windows command line的ss64.com。
在OP中,您尝试使用cmd /v
延迟扩展并将%
替换为!
。
您还尝试了将cmd
命令最多嵌套3个实例。
考虑示例1:
cmd /c echo 1 && echo 2 > file.txt 2>&1
期望是:
cmd /c echo 1
将执行。echo 2 > file.txt 2>&1
将在已经处于cmd
进程中的情况下执行。请考虑示例2:
cmd /c (echo 1 ^&^& echo 2) > file.txt 2>&1
期望是:
cmd /c (echo 1 ^&^& echo 2) > file.txt 2>&1
将记录第1
行(+ 空格)和第2
至file.txt
行。&&
在每个字符之前被前面的^
延迟,并且echo
输出按()
分组,以便file.txt获得所有输出。要尝试的实际命令:
cmd /v /c (powershell -file .\Install.ps1 ^&^& reg add "HKCU\SOFTWARE\Foo\bar" /v "Installed" /d "!date:~4! !time!" /f /reg:64 ^> nul) >> "!userprofile!\install.log" 2>&1
我没有或以前使用过Intune管理扩展来确保成功。 cmd /v
的使用和!
而不是%
的使用取决于您的测试结果等。