将 .ps1 转换为 .bat 不会导致 cmd.exe 达到最大字符长度 - 但为什么呢?

Converting .ps1 to .bat doesn't cause cmd.exe to hit max character length - but why?

基于 和一些 Googling/testing,很明显 cmd.exe 中命令行的最大长度为 8,191 个字符。然而...我的脚本似乎成功地超过了那个长度,我不明白为什么它会起作用。

所以我有:

我意识到这是一个有点奇怪的问题,因为我正试图确定某种关于有效的东西与坏掉的东西的隐藏真相,但我想了解 为什么它有效!

注: 我为我的脚本创建 .bat 的主要原因是因为我有一些小的 'programs' 我需要在我的工作计算机上 运行 并与其他人共享。我们公司的执行政策不允许 运行ning 脚本,如果是 .bat,其他人使用我写的东西会容易得多,因为他们不需要 understand/use PowerShell。他们只需将 .bat 放在正确的位置,点击两次,然后高枕无忧,直到事情发生。

编辑: 这是 cmd.exe window 中的 t运行 相关命令。如果我从 Base64 转换回可读文本,它显然会丢失大约一半的脚本。然而 - 我没有注意到任何问题

  • 8191 字符限制适用于 交互式命令行 和调用 cmd.exe CLI(通过 cmd /c

  • 适用于从批处理文件调用的命令 - 限制接近[1]32KiB32,768)个字符。

    • 但是,它似乎仍然选择性地应用于cmd.exe内部命令,例如echo;相比之下,对 外部程序 的调用,例如 powershell.exe 不受影响(尽管特定的外部程序可能有自己的下限)。

顺便说一句:

linked method of converting PowerShell scripts to batch files 一样聪明,生成的批处理文件 不支持参数 传递给 PowerShell 代码,并添加对此的支持是不切实际的(它也需要对参数进行 Base64 编码,在调用时,这在批处理文件中是不可能的,除非借助非内置实用程序)。

  • 如果您的脚本/批处理文件被编写为在调用时不需要参数或以交互方式提示它们(如您的情况),则无需担心此限制。

  • 但是,出于以下任何原因,您可能需要参数支持:

    • 允许从 cmd.exe(命令提示符)使用参数.
    • 调用批处理文件
    • 允许使用其他支持传递参数的环境中的参数进行调用,特别是任务计划程序和 Windows Run 对话框 (WinKey-R)。
    • 使批处理文件支持拖放(隐式传递拖放文件的路径作为参数)。

至于将 PowerShell 代码包装在批处理文件中的总体原因

  • 批处理文件(.cmd.bat)可以直接启动,就好像它们是可执行文件一样,系统范围.
  • 相比之下,PowerShell 脚本 (.ps1) 不支持,必须通过显式调用 PowerShell CLI 从 PowerShell 外部调用它;请注意,系统可能被配置为断然阻止执行 .ps1 脚本 - 请参阅下一节。

如果您 需要批处理文件中的参数支持,最好但不方便的解决方案是 分发两个个文件:

  • 原始*.ps1文件...
  • 和一个配套批处理文件,具有相同的基本文件名,放置在相同的目录中 - 可以从 外部调用 PowerShell - 其唯一目的是通过 powershell.exe 使用传递参数调用 *.ps1 文件。

例如foo.cmd 将伴随 foo.ps1,具有以下不变的内容:

@powershell.exe -NoProfile -File "%~dpn0.ps1" %*

注:

  • 重要提示:以上假设有效的 PowerShell execution policy 允许执行脚本文件 (.ps1).

    • 如果您不能做出这个假设,请将 -ExecutionPolicy RemoteSigned 放在上面的 -NoProfile 之前(或者,要停用所有检查,-ExecutionPolicy Bypass),但请注意基于 GPO(组策略对象)可能仍会阻止脚本执行。
  • 要调用 PowerShell (Core) 7+,请使用 pwsh.exe 而不是 powershell.exe

  • %~dpn0 扩展为封闭批处理文件本身的完整路径 没有其文件扩展名 ;因此附加 .ps1 以同一目录中的伴随 PowerShell 脚本为目标; 运行 cmd /c call /? 语法解释。

  • %* 传递批处理文件收到的所有参数。


[1] 实际上,限制似乎是:32,767 个字符 在批处理文件中 ,并且 - 减少 3 个字符。 - 32,764 for Powershell(在命令行/通过 CLI 和在 *.ps1 脚本中)。在 PowerShell 中,该限制实际上可能比这更低,因为 PowerShell 将其通过 $env:PATH 定位的可执行文件的名称扩展为它们在后面构建的命令行中的 完整路径 cmd.exe 没有的场景。