What is the command line length limit?

It depends on whom you ask.

The maximum command line length for the CreateProcess function is 32767 characters. This limitation comes from the UNICODE_STRING structure.

CreateProcess is the core function for creating processes, so if you are talking directly to Win32, then that's the only limit you have to worry about. But if you are reaching CreateProcess by some other means, then the path you travel through may have other limits.

If you are using the CMD.EXE command processor, then you are also subject to the 8192 character command line length limit imposed by CMD.EXE.

If you are using the ShellExecute/Ex function, then you become subject to the INTERNET_MAX_URL_LENGTH (around 2048) command line length limit imposed by the ShellExecute/Ex functions. (If you are running on Windows 95, then the limit is only MAX_PATH.)

While I'm here, I may as well mention another limit: The maximum size of your environment is 32767 characters. The size of the environment includes the all the variable names plus all the values.

Okay, but what if you want to pass more than 32767 characters of information to a process? You'll have to find something other than the command line. We'll discuss some options tomorrow.

Comments (16)
  1. Juan Miguel Venturello says:

    Thanks for this blog Raymond, this is very interesting. Looking forward to the answers tomorrow, I can imagine what some of them will be ;)
    This weekend I went through all your blog archives and learnt many, many things I have always wondered about in my win32 developer career, and a few new tricks.

    As many said, this is book material :) Good luck with all and again, thanks,

    Juan Miguel Venturello

  2. Jordan Russell says:

    I never knew ShellExecute imposed such a limitation. Very good to know.

    Here’s an unrelated question that might make for an interesting blog topic:

    Why does FILE_ATTRIBUTE_NORMAL exist, and why is it defined as 0x00000080? Why not just use 0 when no special attributes are set?

  3. Catatonic says:

    What is the limit for _spawnv(), where you supply your own argv to the process? I use this in my code because I don’t have to worry about quoting or escaping special characters.

  4. Catatonic says:

    Whoops, forgot to post the answer! The limit for _spawnv is a measly 1024 bytes.

  5. Anonymous says:

    _spawnv eventually calls CreateProcess but there doesn’t seem to be any limit checks before it calls it (at least in the CRT for VS6).

  6. Anonymous says:

    The CRT for VS6 doesn’t check for that limit at all. Infact, it doesn’t even use arg_len in _cenvarg at all.

  7. Raymond Chen says:

    For historical completeness: The DOS command line length limit was 127 characters.

  8. Catatonic says:

    Interesting. The MSDN documentation for _spawnv must say 1024 bytes for a reason. Just to be safe I’d better stick to it!

  9. Mike Dunn says:

    To pass > 32K chars, use a memory mapped file. You can pass the name of the MMF object (or a handle value, if you let the 2nd app inherit handles from the first) and the length of the memory block on the command line:

    Pass 261004 bytes in the MMF called "MyMMFThingy"

    appnumber2.exe /n "MyMMFThingy" /l 261004

    Then of course you add some sync code so that the MMF stays around for as long as both apps need it to.

  10. Raymond Chen says:

    Mike got it basically right. Except that you don’t want to pass the length on the command line; somebody could pass a bogus length and cause you to crash. And coming up with a unique name can be tricky (plus giving it a name opens you up to attackers who can grab the shared memory object file and look at or even mess with it before the child looks at it — this is a data tampering / information disclosure attack; you can prevent this by applying ACLs to your shared memory object). I prefer an anonymous inheritable handle, which avoids the synchronization problem as well.

  11. Mike Dunn says:

    Both good points, Raymond. This teaches me that I shouldn’t write code with security implications at 12:25 AM ;)

  12. James Curran says:

    I love the Code/History notes. Do you take requests?

    One of the bugaboos of Undocumented MSDOS coding was attempting to change the master environment variables block. (If I recall correctly, by DOS6, there were six different ways to find it — none of which were guaranteed to work, so you had to try all six, and use the number which came up the most).
    Which bring us to the question — Why did microsoft never provide a nice simple (say, INT 21h) interface to add & remove evars.

  13. Raymond Chen says:

    Because you aren’t supposed to change the environment of another process, much less the root environment block. Unix doesn’t let you do it either.

  14. Paraesthesia says:

    Dynamic FxCop Dependency List Using MSBuild

Comments are closed.