Issue
Based on a related question and some Googling/testing, it is pretty clear that the maximum length of a command line in cmd.exe
is 8,191
characters. However…my script seems to successfully exceed that length, and I can’t figure out why it works.
So I have:
- A script written/saved as a
.ps1
- I’m converting it to a
.bat
using the method from Converting PowerShell to Batch - If I run the
.bat
– there don’t seem to be any issues - If I try to echo the
$encoded
command or just remove@echo off
before running the.bat
– it is easy to see that the length/content of$encoded
has been truncated…yet it works as expected
I realize this is a bit of a strange question since I’m trying to ascertain some kind of hidden truth about something that works vs. something that is broken, but I’d like to understand why it is working!
Note:
The primary reason I’m creating a .bat
for my script is because I have a number of small ‘programs’ that I need to run on my work computer and share with others. Our company’s execution policies don’t allow running scripts, and it is much easier for others to use something I’ve written if it is a .bat
since they won’t need to understand/use PowerShell
. They can just place the .bat
in the right place, give it two clicks, and then sit back and relax until something happens.
EDIT: Here’s the truncated command in the cmd.exe
window. If I convert from Base64 back to readable text, it is clearly missing about half of the script. Yet – I’m not noticing any problems
Solution
-
The
8191
-character limit applies to the interactive command line and calls tocmd.exe
‘s CLI (viacmd /c
) -
It does not apply to commands invoked from batch files – there the limit is close to[1]
32KiB
(32,768
) characters.- However, it still seems to apply selectively to
cmd.exe
‘s internal commands, such asecho
; by contrast, a call to an external program such aspowershell.exe
is not affected (though it is possible for specific external programs to have their own, lower limits).
- However, it still seems to apply selectively to
As an aside:
As clever as the linked method of converting PowerShell scripts to batch files is, the resulting batch files lack support for arguments to be passed through to the PowerShell code, and adding support for that would be impractical (it would require Base64-encoding the arguments too, at invocation time, which isn’t possible from a batch file except with the help of non-built-in utilities).
- Note: If your script / batch file is written to either require no arguments on invocation or to prompt for them interactively (as in your case), this limitation is not a concern.
If you do need argument support, the best – but inconvenient – solution is to distribute two files:
- the original
*.ps1
file… - and a companion batch file, with the same base file name, to be placed in the same directory – which can be invoked from outside PowerShell – whose sole purpose is to invoke the
*.ps1
file viapowershell.exe
with pass-through arguments.
E.g. foo.cmd
would accompany foo.ps1
, with the following – invariant – content:
@powershell.exe -NoProfile -File "%~dpn0.ps1" %*
Note: To call PowerShell (Core) 7+ instead, use pwsh.exe
instead of powershell.exe
.
[1] In practice, the limits appear to be: 32,767
characters in batch files, and – lower by 3 chars. – 32,764
for Powershell (both on the command line / via the CLI and in *.ps1
scripts). In PowerShell, the limit may in practice be even lower than that, because PowerShell expands the names of executables it locates via $env:PATH
to their full paths in the command lines constructed behind the scenes, which cmd.exe
doesn’t do.
Answered By – mklement0
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0