我们可以在PowerShell中调用Bat命令而不调用/调用Bat文件吗?

huangapple go评论65阅读模式
英文:

Can we call Bat command within powershell without calling/invoking a bat file?

问题

可以在PowerShell中调用Bat命令而不调用/调用Bat文件吗?

例如,Bat脚本:

@echo [off]
echo sample batch script
pause

在PowerShell中本身

命令必须被执行。

英文:

Can we call Bat command within powershell without calling/invoking a bat file?

For example bat script:

@echo [off]
echo sample batch script
pause

In powershell itself

Commands must be executed.

答案1

得分: 2

以下是翻译好的部分:

你可以模拟大多数批处理操作。

  1. 例如 PAUSE
  2. ECHO 类似于 Write-Host$Var | Out-Host

此外,你可以使用 cmd.exe --% /c 调用批处理命令,但是,一旦 cmd.exe 退出,执行命令的环境就消失了,其中设置的任何环境变量也会消失。

另一方面,cmd.exe 的输出可以保存到变量中。
在这个示例中:

  1. Stop-Parsing标记之后的所有内容都会未经处理地传递给CMD。
  2. dir 命令的路径是通过首先设置一个环境变量 $Env:DirPath = 'C:\Users\public',然后在批处理中检索环境变量 %DirPath% 动态提供的。
  3. 使用 $Var = $(<code>) 将输出保存在 $Var 中。

注意: 闭括号不在 cmd.exe --% 行的末尾,因为如果在末尾,它将被 PowerShell 忽略。

$Env:DirPath = 'C:\Users\public'
$Var = $(
    cmd.exe --% /c dir "%DirPath%" /w
)
$Var

你还应该能够在 cmd.exe --% 命令中使用 & 执行多个批处理命令,但我还没有进行过实验,所以不确定会如何运行。

英文:

You can emulate most things BATCH.

  1. For example PAUSE.
  2. And ECHO is similar to Write-Host and $Var | Out-Host.

Also, you can call BATCH commands with cmd.exe --% /c, BUT, as soon as cmd.exe exits, the environment the command was executed in is gone - along with any environment variables that were set.

On the other hand, cmd.exe's output can be saved to a variable.
In this example:

  1. Everything after the Stop-Parsing token is passed unprocessed to CMD.
  2. The path given to dir is dynamically provided by first setting an environment variable $Env:DirPath = 'C:\Users\public', and then retrieved the environment variable in BATCH %DirPath%.
  3. Uses $Var = $(<code>) to save output in $Var.

NOTE: The closing parentheses is NOT at the end of the cmd.exe --% line, because, if it was, it would be ignored by PowerShell.

$Env:DirPath = 'C:\Users\public'
$Var = $(
    cmd.exe --% /c dir "%DirPath%" /w
)
$Var

You should also be able to use & in the cmd.exe --% command to execute more than one BATCH command, but I haven't experimented with that, so not sure how that would work out.

答案2

得分: 1

  • 无法在PowerShell中直接执行批处理命令,因为PowerShell无法理解它们。

  • 虽然有一个小子集的命令在cmd.exe(批处理文件的解释器)和PowerShell中具有相同的名称,PowerShell通过为其不同命名的命令提供_别名_(例如,dir用于Get-ChildItem)来提供对这些少数命令的调用仅在所有但最简单的情况下才能正常工作,因为PowerShell的参数语法与cmd.exe的语法根本不同。

  • 可以通过cmd.exe的CLI执行批处理命令,即通过**cmd /c(运行cmd /?以获取详细信息)或通过将命令_管道_到cmd.exe**(... | cmd),但请注意以下事项:

    • 与批处理文件一样,这些调用在一个_子_进程中运行,因此对环境变量的修改对调用者是不可见的,例如。

    • 这些命令被解释为_交互式_cmd.exe会话中的命令,这意味着for循环必须使用%i而不是%%i,例如。

    • 传递_多个_批处理命令有_严重限制_

      • 使用cmd /c,您只能传递_单个_行(任何额外的行将被忽略),因此您必须使用cmd.exe&运算符来顺序执行多个命令,这仅在这些命令不依赖于变量时才起作用_相互_。

        OK - 两个命令不相互依赖。

        cmd /c 'ver & date /t'

        !! NOT OK - %FOO%的值不会被echo调用看到

        cmd /c '(Set FOO=bar) & echo %FOO%'

      • 但是,您可以通过/v选项启用延迟变量扩展功能,在这种情况下,使用!...!而不是%...%有效

        OK - 由于/v和!FOO!

        cmd /v /c '(Set FOO=bar) & echo !FOO!'

      • 此外,您可以使用一个可展开(双引号引起的)字符串("..."来嵌入cmd /c调用中_PowerShell_变量的值,作为Darin的回答中显示的--%技术的替代方法;如果需要嵌入"字符,请将其转义为`"(或""):

        $foo = 'bar' # 定义一个PowerShell变量
        cmd /c "echo $foo" # 将其值嵌入“...”字符串

  • 使用多行管道输入

    • 即使您将多行输入字符串以@echo off开头,您仍然会看到cmd.exe启动横幅 Microsoft Windows [Version ...])和一个提示字符串(例如,C:\>),并且每个命令的源代码行将在执行结果之前打印出来。

    • 除非代码使用显式的exit调用退出,否则cmd.exe的退出代码将_不_反映最后一个执行的命令的退出代码。

    • 要了解更多信息以及在幕后创建一个_临时批处理文件_以避免这些限制的帮助函数,请参阅此回答

    • 这是一个使用here-string来将多个命令传递给cmd.exe的示例;如上所述,您将看到启动横幅和一个提示字符串,并且每个命令的输出之前将打印出源代码行:

      @'
      @echo off
      ver
      date /t
      Set FOO=bar
      echo %FOO%
      exit
      '@ | cmd.exe

英文:
  • You cannot execute batch-file commands directly in PowerShell, because PowerShell doesn't understand them.

    • While there is a small subset of commands that have the same name in both cmd.exe (the interpreter of batch files) and PowerShell, by way of PowerShell providing aliases for its differently named commands (e.g., dir for Get-ChildItem), calls to these few commands only work the same in all but the simplest cases, given that PowerShell's parameter syntax differs fundamentally from that of cmd.exe
  • You can execute batch-file commands via cmd.exe's CLI, namely either via cmd /c (run cmd /? for details) or by piping commands to cmd.exe (... | cmd), but note the following:

    • Like batch files, such calls run in a child process, so that modifications to environment variables wouldn't be seen by the caller, for instances.

    • The commands are interpreted as in interactive cmd.exe sessions, which notably means that for loops must use %i rather than %%i, for instance.

    • Passing multiple batch-file commands has severe limitations:

      • With cmd /c, you can only pass a single line (any additional lines are ignored), so you must use cmd.exe's & operator to sequence multiple commands, which only works if these commands do not depend on each other with respect to variables.

        # OK - the two commands aren't interdependent.
        cmd /c 'ver & date /t'
        
        # !! NOT OK - the %FOO% value isn't seen by the echo call
        cmd /c '(Set FOO=bar) & echo %FOO%'
        
        • However, you can enable the delayed-variable-expansion feature via the /v option, in which case using !...! instead of %...% does work:

          # OK - thanks to /v and !FOO!
          cmd /v /c '(Set FOO=bar) & echo !FOO!'
          
        • Separately, you can use an expandable (double-quoted) string ("...") in order to embed the value of PowerShell variables in the cmd /c call, as an alternative to the --% technique shown in Darin's answer; if you need to embed " characters, escape them as `" (or ""):

          $foo = 'bar' # define a PowerShell variable
          cmd /c "echo $foo" # embed its value in the "..." string
          
      • With multiline pipeline input:

        • Even if you start your multiline input string with @echo off, you will invariably see cmd.exe's startup banner ( Microsoft Windows [Version ...]) and one prompt string (e.g, C:\>), and the source code line of each command will print either way before the result of its execution.

        • Unless the code exits with an explicit exit call, the cmd.exe's exit code will not reflect the exit code of the last command executed.

        • For more information as well as a helper function that creates a temporary batch file behind the scenes to avoid these limitations, see this answer

        • Here's an example that uses a here-string to feed multiple commands to cmd.exe; as noted, you'll see the startup banner and one prompt string, and the source-code lines will print before each command's output:

          @'
          @echo off
          ver
          date /t
          Set FOO=bar
          echo %FOO%
          exit
          '@ | cmd.exe
          

huangapple
  • 本文由 发表于 2023年4月13日 16:12:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76003139.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定