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

C# 如何绕过命令行长度限制?,c#,windows,command-line,C#,Windows,Command Line,我一直在做一个小而简单的程序,我把文件放到上面,根据一定的规则,它们被移动到不同的地方 该程序运行正常,除非我删除了多个文件,然后它会返回一个错误(这似乎是Windows最多的错误),即启动命令“c:\myapp.exe\file\file\file”太长 我意识到我可以设置一个后台进程,但我真的希望这个程序不要在后台运行(大部分时间是空闲的) 有没有办法绕过这个限制?我会修改应用程序,从特定位置(例如文件系统上的特定文件夹)拾取文件,而不是在命令行上指定每个文件 更新: 如果要求能够通过Win

我一直在做一个小而简单的程序,我把文件放到上面,根据一定的规则,它们被移动到不同的地方

该程序运行正常,除非我删除了多个文件,然后它会返回一个错误(这似乎是Windows最多的错误),即启动命令“c:\myapp.exe\file\file\file”太长

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


有没有办法绕过这个限制?

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

更新:


如果要求能够通过Windows资源管理器将项目拖到.exe上,以按Mark所述启动应用程序,则可以将所有文件放在一个文件夹中,并将整个文件夹放在.exe上。

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

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

如果要删除Windows资源管理器中的文件,则可以将您自己的删除处理程序实现为Shell扩展处理程序,请参见:

在上,您将找到一个很好的介绍如何编写这样的扩展

给出了一个Drop处理程序的示例(对于其他一些用例,但这并不重要)


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

在尝试获取长路径上的安全详细信息时,我遇到了类似的问题。 我的解决方案是在路径长度过长时映射驱动器。在上查看我的解决方案

Unix命令通常有一个或两个长度无限的参数。其中一些命令添加了参数,这些参数可以从文件或标准输入中获取。因此,您有一个命令,它可以整理参数列表,并将它们通过管道传输到临时文件,或通过管道传输到stdout

另请参见xargs,它可以获取参数列表,并使用所有参数调用命令,也可以成批调用命令。

来自:

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

因此,您必须解决一些提到的解决方法(此外,我链接的msdn博客上还有另一个解决方法)。

我认为拖放处理程序可能是一种方法,但它似乎相当繁重

另一种解决方案是使用资源管理器上下文菜单处理程序。有了这个选项,您可以选择所有文件,但不是拖动它们,而是右键单击,然后选择新的菜单项“发送到”

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

  • 启动程序,并将文件列表提供给标准输入
  • 将文件列表写入一个临时文件,只需一个命令参数即可启动程序—临时文件列出要处理的文件。在命令行上,列表文件通常以“@”作为前缀,以区别于普通文件名

  • 如何绕过命令行长度限制?将整个命令写入批处理文件,例如“C:\Users\Johnny\Documents\mybatch.bat”。像在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);
    

    是的,这是一个选项,但它需要在后台运行,当你说你“…我把文件放到的简单程序…”你是指你把文件放到的GUI窗口吗?您可以在需要时手动启动应用程序,或在任务计划程序中设置新任务以定期运行应用程序。否,我认为他的意思是通过windows资源管理器将文件拖放到.exe上。正确-将文件拖放到桌面上的exe图标上,以便example@Crash893:请查看我编辑的答案,看看它是否适合您。拖放文件是为了方便。我不认为在文本文件中添加名称会更方便啊,我看到你已经向其他一些回答者提供了澄清,我以为你正在将内容放到你编写的GUI应用程序上,在那里你可以处理删除数据。我没有意识到您正在浏览shell。不如在后台运行它,但不如选择几个文件并将其放到屏幕上。缺点是,根据文件夹路径的长度,它仍然无法解决问题+1为理想