【问题标题】:Powershell / cmd - Redirecting embedded script's output streams to filePowershell / cmd - 将嵌入式脚本的输出流重定向到文件
【发布时间】:2019-07-11 02:43:15
【问题描述】:

我遇到的情况是 cmd 脚本必须启动 powershell 脚本 (install.ps1),如果 cmd 还没有,则提升为管理员。启动 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 获得相同的行为?

powershell -Command "Start-Process -WindowStyle Hidden -Verb RunAs -Wait powershell \"-NoProfile -ExecutionPolicy Bypass -Command %~dp0pg.ps1 *^> %CD%\log.txt\""

【问题讨论】:

    标签: powershell cmd


    【解决方案1】:

    *>log.txt 重定向移动到Invoke-Command 块中原则上,但您的问题是在Windows PowerShell(而不是PowerShell Core)中有一个进程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 认为@ 987654335@ 被不加引号,因为它不能将\" 序列识别为嵌入双引号 - 只有 PowerShell 可以。

    • 与您的原始命令一样,假设%~dp0 - 批处理文件的文件夹目录都不是。路径 - 也不是 %CD% - 调用者的工作目录。路径 - 包含空格或其他特殊字符。这将需要额外的引用/转义。

    【讨论】:

    • 再次感谢!后续问题 - 有什么方法可以通过“-File”而不是“-Command”调用 PS 脚本来使其工作? -File 方法解决了我们的大多数边缘情况 - arg 格式化问题,而 -Command 没有,但我无法让日志记录以与您在此处所做的类似方式工作。对两者进行一些阅读,我猜这是 -File 和 -Command 之间的区别,它同时修复了 arg 错误并防止登录此方法,但也许我缺少一个技巧来获得两全其美。
    • @allison:对于-File> 不可用。您可以使用 Start-Process' -RedirectStandarOutput-RedirectStandardError 参数,但请注意,您将无法捕获 combined 输出。使用 powershell -EncodedCommand 会给您最大的灵活性,但这需要您将 PowerShell 命令字符串 Base64 编码为 UTF-16LE 字符串,这在批处理文件中很难获得。
    猜你喜欢
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    相关资源
    最近更新 更多