将 .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
个字符。然而...我的脚本似乎成功地超过了那个长度,我不明白为什么它会起作用。
所以我有:
- 脚本 written/saved 作为
.ps1
- 我正在使用Converting PowerShell to Batch
中的方法将其转换为.bat
- 如果我 运行
.bat
- 似乎没有任何问题
- 如果我尝试回显
$encoded
命令或只是在 运行 宁 .bat
之前删除 @echo off
- 很容易看出 [=60= $encoded
的 ] 已被 t运行 分类...但它按预期工作
我意识到这是一个有点奇怪的问题,因为我正试图确定某种关于有效的东西与坏掉的东西的隐藏真相,但我想了解 为什么它有效!
注:
我为我的脚本创建 .bat
的主要原因是因为我有一些小的 'programs' 我需要在我的工作计算机上 运行 并与其他人共享。我们公司的执行政策不允许 运行ning 脚本,如果是 .bat
,其他人使用我写的东西会容易得多,因为他们不需要 understand/use PowerShell
。他们只需将 .bat
放在正确的位置,点击两次,然后高枕无忧,直到事情发生。
编辑: 这是 cmd.exe
window 中的 t运行 相关命令。如果我从 Base64 转换回可读文本,它显然会丢失大约一半的脚本。然而 - 我没有注意到任何问题
8191
字符限制适用于 交互式命令行 和调用 cmd.exe
的 CLI(通过 cmd /c
)
它不适用于从批处理文件调用的命令 - 限制接近[1]32KiB
(32,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
没有的场景。
基于 cmd.exe
中命令行的最大长度为 8,191
个字符。然而...我的脚本似乎成功地超过了那个长度,我不明白为什么它会起作用。
所以我有:
- 脚本 written/saved 作为
.ps1
- 我正在使用Converting PowerShell to Batch 中的方法将其转换为
- 如果我 运行
.bat
- 似乎没有任何问题 - 如果我尝试回显
$encoded
命令或只是在 运行 宁.bat
之前删除@echo off
- 很容易看出 [=60=$encoded
的 ] 已被 t运行 分类...但它按预期工作
.bat
我意识到这是一个有点奇怪的问题,因为我正试图确定某种关于有效的东西与坏掉的东西的隐藏真相,但我想了解 为什么它有效!
注:
我为我的脚本创建 .bat
的主要原因是因为我有一些小的 'programs' 我需要在我的工作计算机上 运行 并与其他人共享。我们公司的执行政策不允许 运行ning 脚本,如果是 .bat
,其他人使用我写的东西会容易得多,因为他们不需要 understand/use PowerShell
。他们只需将 .bat
放在正确的位置,点击两次,然后高枕无忧,直到事情发生。
编辑: 这是 cmd.exe
window 中的 t运行 相关命令。如果我从 Base64 转换回可读文本,它显然会丢失大约一半的脚本。然而 - 我没有注意到任何问题
8191
字符限制适用于 交互式命令行 和调用cmd.exe
的 CLI(通过cmd /c
)它不适用于从批处理文件调用的命令 - 限制接近[1]
32KiB
(32,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
没有的场景。