我遇到这样一种情况,一个cmd脚本必须启动powershell脚本(install.ps1),如果该cmd尚未启动,则提升为admin。启动powershell的行如下所示:
powershell -WindowStyle Hidden "Start-Process powershell \"-NoP -Exec Bypass -File `\"%~dp0install.ps1`\" %args%\" -Verb runAs -Wait"
或者这也可行:
powershell -WindowStyle Hidden "Start-Process powershell \"-NoP -Exec Bypass invoke-command { %~dp0install.ps1 %args% } \" -Verb runAs -Wait"
我想将install.ps1脚本的输出重定向到文件以进行日志记录,但是这样做很麻烦。类似于下面的内容将生成log.txt文件,但是输出仍将显示在控制台中,并且结果log.txt文件将为空:
powershell -WindowStyle Hidden "Start-Process powershell \"-NoP -Exec Bypass invoke-command { %~dp0install.ps1 %args% } \" *> log.txt -Verb runAs -Wait"
将*> log.txt
部分移动到Start-Process块内部(紧接invoke-command块之后),我认为这是关键,似乎根本没有运行脚本(或者闪烁了控制台中的错误显示得太快,因为它会立即关闭)。
当我想要的数据被埋入cmd文件执行的几层Powershell中时,是否可以实现这种记录行为?
从技术上讲,通过创建一个由cmd调用/提升的Powershell包装器脚本,然后在包装器中调用install.ps1脚本并在该调用中分配日志记录,可以使此方法起作用。不幸的是,额外的脚本层会导致一堆其他棘手的问题,甚至是更关键的问题,这些问题涉及如何在命令行中将参数一直传递到正确的实际安装脚本,因此我们实际上是在尝试避免这种做法。
感谢@ mklement0提供了需要转义重定向的指针,这是我的问题。后续问题-以下命令可以很好地记录到文件,但是在调用PS脚本(“ -Command%〜dp0pg.ps1”)时,是否可以使用-File而不是-Command来获得相同的行为?< / p>
powershell -Command "Start-Process -WindowStyle Hidden -Verb RunAs -Wait powershell \"-NoProfile -ExecutionPolicy Bypass -Command %~dp0pg.ps1 *^> %CD%\log.txt\""
答案 0 :(得分:2)
将*>log.txt
重定向移至Invoke-Command
块在原理上是有效的 ,但是您的问题是在Windows PowerShell中(而不是PowerShell Core >)使用{em> elevation (以管理员身份)通过-Verb RunAs
调用的进程,默认为C:\Windows\System32
作为工作目录,而不是呼叫者的工作目录。
除了您可能并不打算在C:\Windows\System32
中创建日志文件之外,该命令还将失败,因为写入该位置要求调用者已经被提升
最简单的解决方案是使*>
重定向到使用完整路径指定的文件:
powershell -Command "Start-Process -WindowStyle Hidden -Verb RunAs -Wait powershell \"-NoProfile -ExecutionPolicy Bypass -Command %~dp0pg.ps1 *^> %CD%\log.txt\""
注意:
不需要Invoke-Command
-只需直接调用*.ps1
文件即可;但是,我添加了-Command
,以便更清楚地将命令行的其余部分解释为PowerShell代码(而不是仅包含参数的脚本文件路径)。
由于>
是cmd.exe
元字符,因此必须将其转义为^>
才能通过到PowerShell-也许令人惊讶, cmd.exe
认为>
是不带引号的,因为它无法将\"
序列识别为嵌入的双引号-仅PowerShell会。
与您的原始命令一样,假定两者都不是%~dp0
-批处理文件的文件夹目录。路径-也不%CD%
-呼叫者的工作目录。路径-包含空格或其他特殊字符。这需要附加的引号/转义。