【问题标题】:How to get around the command line length limit?如何绕过命令行长度限制?
【发布时间】:2011-02-24 09:40:19
【问题描述】:

我一直在开发一个小而简单的程序,我将文件拖放到该程序上,并根据某些规则将它们移动到不同的地方。

该程序运行良好,除非我删除了多个文件,然后它会返回一个错误(这似乎比任何东西都多),即启动命令“c:\myapp.exe \file \file \file " 太长了。

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

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

【问题讨论】:

    标签: c# windows command-line


    【解决方案1】:

    来自this blog

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

    因此,您将不得不解决一些提到的解决方法(此外,我链接的 msdn 博客上还有另一种解决方法)。

    【讨论】:

      【解决方案2】:

      如果您想在 Windows 资源管理器中删除文件,那么您可以将自己的 Drop Handlers 实现为 Shell Extension Handlers,请参阅:

      The Complete Idiot's Guide to Writing Shell Extensions 你会找到一个很好的介绍如何编写这样的扩展。

      part VI 给出了 Drop Handler 的示例(对于其他一些用例,但没关系)。

      关于 Drop Shell Extension Handler,您的程序将收到有关所有已删除文件的完整信息,并且您无需启动子程序并将所有文件作为命令之类的参数。

      【讨论】:

      • 对不起,我在这个问题上隔了一段时间,谢谢我试试看。因为我现在没有时间测试它,而且你的票数最多,所以你得到了赏金
      • 我们应该使用什么 clsid?
      • @SepehrM:如果我理解正确,您只需生成新的唯一 GUID 并将其用作 Shell 扩展处理程序的 clsid。只需在 Visual Studio 中选择“工具”/“创建 GUID”菜单即可启动该实用程序,这有助于生成新的唯一 GUID。
      • @Oleg 感谢您的回复。是的,但我的工具菜单中没有“生成 GUID”。我正在使用 VS 2013 Update 4,我的项目在 WPF 中使用 .NET 4.0。
      • @Oleg 我找到了解决方案:stackoverflow.com/questions/13882434/…
      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 拖放文件是为了方便。我不认为将名称添加到文本文件会更方便
        • 啊,我看到您已经向其他一些回答者提供了澄清,我以为您正在使用您编写的 GUI 应用程序,您可以在其中处理放置数据。我没有意识到你正在通过 shell。
        【解决方案5】:

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

        更新:

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

        【讨论】:

        • 是的,这是一个选项,但它需要它在后台运行
        • 当您说“...我将文件放到...上的简单程序”时,您是指您将文件放到其中的 GUI 窗口吗?您可以在需要时手动启动应用程序,或在任务计划程序中设置新任务以定期运行您的应用程序。
        • 不,我认为他的意思是通过Windows资源管理器将文件拖放到.exe上。
        • 正确 - 例如将文件拖放到桌面上的 exe 图标上
        • @Crash893:请查看我编辑的答案,看看它是否适合您。
        【解决方案6】:

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

        【讨论】:

        • 没有在后台运行它那么糟糕,但也没有像选择几个文件并将其放到上面那样流畅。缺点是它仍然无法解决问题,具体取决于文件夹路径的长度。为这个想法 +1
        • 我的印象是您达到了允许的命令行参数的限制,而不是命令本身的限制。我想我误解了。您(或其他任何人)知道实际的限制是多少吗?
        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

            【解决方案9】:

            如何绕过命令行长度限制?将整个命令写入批处理文件,例如到“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);
            

            【讨论】:

            • 即使您将 UseShellExecute 设置为 false,这仍然受 32767 个字符的限制。
            猜你喜欢
            • 1970-01-01
            • 2016-04-27
            • 2016-07-13
            • 1970-01-01
            • 2019-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多