使用T形三通从另一个外壳运行PowerShell

使用T形三通从另一个外壳运行PowerShell,powershell,cmd,command-line,command-line-interface,Powershell,Cmd,Command Line,Command Line Interface,我想学习从另一个shell或语言执行PowerShell命令,例如Pythonos.system()。我希望实现以下目标: 执行PowerShell命令 将输出同时发送到控制台和文件 返回命令退出代码 假设使用cmd.exe作为调用方环境,我认为这给出了我想要实现的一个想法: powershell -NoProfile -command "& { cat foo.txt | Tee-Object ps-log.txt; exit $LASTEXITCODE }" e

我想学习从另一个shell或语言执行PowerShell命令,例如Python
os.system()
。我希望实现以下目标:

  • 执行PowerShell命令
  • 将输出同时发送到控制台和文件
  • 返回命令退出代码
  • 假设使用cmd.exe作为调用方环境,我认为这给出了我想要实现的一个想法:

    powershell -NoProfile -command "& { cat foo.txt  | Tee-Object ps-log.txt; exit $LASTEXITCODE }"
    echo %errorlevel%
    
    这里有一些问题。首先,我不能在命令中使用引号,例如:

    powershell -NoProfile -command "& { cat `"foo bar.txt`"  | Tee-Object ps-log.txt; exit $LASTEXITCODE }"
    
    cat
    参数似乎是无引号传递的,因此
    cat
    查找“bar.txt”参数

    我认为
    $LASTEXITCODE
    很快就会被扩展,也就是说在执行
    cat
    之前

    &
    不方便使用,因为它不接受包含参数的单个命令行字符串。
    &
    的替代方法是
    iex
    ,但是我无法从cmd.exe使用它。事实上:

    powershell  -NoProfile -command  {iex cat  foo.txt}
    
    返回:

    iex cat foo.txt
    

    cmd.exe
    ,使用以下(
    -c
    -Command
    的缩写):

    • 没有理由在传递给
      -Command
      的字符串中使用
      &{…}
      ——只需使用
      ..

    • Escape embedded
      chars.as
      \”
      (PowerShell(Core)7+也接受

      • 或者,正如所指出的,您可以在传递给
        -Command
        /
        -c
        “…”
        字符串中使用
        '.
        (单引号),假设不需要
    • 由于该命令仅涉及PowerShell本机命令(在Windows上,
      cat
      只是的别名),因此未设置
      $LASTEXITCODE
      ,因为它仅反映外部程序的退出代码。而是应用,这是一个布尔值,指示最近执行的管道中的命令是否发出了任何错误

      • -not
        对该值求反意味着
        $true
        被转换为
        $false
        $false
        被转换为
        $true
        ,这些值被转换为外部整数,
        $false
        映射为
        0
        $true
        映射为
        1

    Powershell支持单引号,这让我在这种情况下节省了很多时间。它的好处是:它们清晰易懂。但请注意,变量扩展在单引号字符串中不起作用

    powershell -NoProfile -command "cat 'foo bar.txt' | tee ps-log.txt"
    

    除此之外,请看一下mklement0答案中的有用建议。

    作为旁白:非常感谢。它是有效的(顺便说一句,有一个
    }
    剩菜),但我不确定幕后发生了什么。我认为,给定命令
    foo.exe argstring
    ,Windows cmd将
    argstring
    按原样发送到
    foo.exe
    ,由后者决定如何解析字符串。具有Unix根目录的软件将
    \“
    解析为文本
    。PowerShell在这里有点奇怪,因为它广泛地记录了它的backtick转义特性,但它自己的可执行PowerShell.exe不遵循此约定。如果我的猜测是错误的,请纠正我。谢谢你指出拼写错误,@antonio-现在修复了。虽然可能会让人困惑,但PowerShell CLI的行为与常规PowerShell代码不同,以便与Windows上命令行上转义
    字符的最广泛使用的约定保持一致。(在Windows上传递参数的底层体系结构非常不幸。)然而,与此相反,当PowerShell解析外部程序的参数时,基本问题仍然存在,尽管最终采取了一些措施来解决这个问题-请参阅。@antonio:另一种说法是:unescaped
    仅具有CLI的语法功能,需要
    是PowerShell在CLI解析后应执行的源代码的一部分,\”-转义。也就是说,
    \“
    在PowerShell计算命令字符串并具有PowerShell的语法功能时变为
    。请注意,如果您使用的是PowerShell(核心),最好使用
    ”“
    在命令行上,因为
    \”
    实际上可以破坏
    cmd.exe
    的语法;例如,
    powershell-NoProfile-c“\“foo&bar\”
    失败,不像
    pwsh-NoProfile-c““foo&bar”“
    谢谢,我确实意识到了这一点,但是,尽管我可以在将变量发送到PowerShell之前展开变量,但参数字符串可以有单引号。所以我需要找到一个转义机制:
    \“它是foo\”
    有效;我找不到等效的
    \'it's foo\'
    工作。
    powershell -NoProfile -command "cat 'foo bar.txt' | tee ps-log.txt"