如何绕过命令行长度限制?

时间:2010-05-26 21:14:38

标签: c# windows command-line

我一直致力于一个小而简单的程序,我将文件放到其上,根据certian规则,它们被移动到不同的地方。

该程序运行正常,除非我删除多个文件,然后它启动一个错误(看起来比Windows更多)启动命令“c:\ myapp.exe \ file \ file \ file “太长了。

我意识到我可以设置一个后台进程,但我真的更希望这个程序不会在后台运行(大部分时间它都会空闲)。

有没有解决这个限制的方法?

9 个答案:

答案 0 :(得分:14)

如果要删除与Windows资源管理器相关的文件,则可以将自己的Drop Handler实现为Shell扩展处理程序,请参阅:

The Complete Idiot's Guide to Writing Shell Extensions上,您会找到一个很好的介绍如何编写此类扩展。

part VI给出了Drop Handler的一个例子(对于其他一些用例,但无关紧要)。

关于Drop Shell扩展处理程序,您的程序将收到有关所有已删除文件的完整信息,您无需使用所有文件作为命令参数启动子程序。

答案 1 :(得分:14)

来自this blog

  • CreateProcess函数的最大命令行长度为32767个字符。此限制来自UNICODE_STRING结构。
  • 如果您使用的是CMD.EXE命令处理器,那么您还需要遵守CMD.EXE强加的8192字符命令行长度限制。
  • 如果您正在使用ShellExecute / Ex功能,那么您将受到ShellExecute / Ex功能强加的INTERNET_MAX_URL_LENGTH(大约2048年)命令行长度限制。
  • 您的环境的最大大小为32767个字符。环境的大小包括所有变量名称加上所有值。

所以你必须解决一些上面提到的解决方法(同样,在我链接的msdn博客上还有另一种解决方法)。

答案 2 :(得分:2)

我认为拖放处理程序可能是一种方法,但它看起来很重。

另一种解决方案是使用Explorer Context Menu处理程序。有了这个,您将选择所有文件,而不是拖动它们,右键单击,然后选择新的菜单项“发送到”。

选择菜单项后,它会将命令列表传递给您的程序。有几种方法可以做到这一点:

  1. 启动您的程序,并将文件列表提供给标准输入
  2. 将文件列表写入临时文件,并使用一个命令参数启动程序 - 列出要处理的文件的临时文件。列表文件通常在命令行上以“@”为前缀,以区别于普通文件名。

答案 3 :(得分:1)

我修改应用程序以从特定位置(例如文件系统上的特定文件夹)获取文件,而不是在命令行上指定每个文件。

<强>更新

如果要求是能够通过Windows资源管理器将项目拖动到.exe上以启动Mark提到的应用程序,那么您可以将所有文件放入一个文件夹并将整个文件夹放在.exe上。 / p>

答案 4 :(得分:1)

当文件被拖放到您的应用程序上时,将文件名列表写入文本文件,然后将该文件的位置提供给您的程序。然后,目标程序可以读入此文件并逐行处理。这样您只需传递一个文件名。

答案 5 :(得分:1)

我认为最简单的解决方案是修改您的应用程序以接受目录作为参数而不是文件列表。这将允许您将多个文件复制到一个目录中。然后,您可以将文件夹拖放到可执行文件中。然后它将运行一个命令,如“c:\ myapp.exe \ folder-with-files-in-it”,它不应该遇到你现在遇到的命令行参数限制。

答案 6 :(得分:1)

当我尝试在很长的路径上获取安全性详细信息时,我遇到了类似的问题。 我的解决方案是在路径长度太长时映射驱动器。看看我的解决方案 How do I get the security details for a long path?

答案 7 :(得分:1)

Unix命令经常有一个或两个可以是无限长度的参数。其中一些命令添加了参数,这些参数可以从文件或标准输入中获取这些参数。因此,您有一个命令可以打开参数列表,并将它们传递给临时文件,或者将它们传递给stdout。

另请参阅xargs,它可以获取参数列表,并使用所有参数或批量调用命令。

答案 8 :(得分:1)

如何绕过命令行长度限制?将整个命令写入批处理文件,例如到&#34; C:\ Users \ Johnny \ Documents \ mybatch.bat&#34;。像在cmd中那样写(不需要逃避任何事情)。然后,在您的代码中只需调用该文件:

strCmdText = "C:\\Users\\Johnny\\Documents\\mybatch.bat";

ProcessStartInfo ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + strCmdText);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = true;

Process.Start(ProcessInfo);