【问题标题】:How to pass context menu parameters to Java ProcessBuilder如何将上下文菜单参数传递给 Java ProcessBuilder
【发布时间】:2023-09-09 01:43:01
【问题描述】:

我正在使用 Java ProcessBuilder 在 Windows 上打开带有特定程序的文件。

它本身工作正常,使用以下代码:

ProcessBuilder p = new ProcessBuilder();
p.command("C:\\Program Files (x86)\\...\\program.exe", file.getAbsolutePath());

我想做的是从该程序中调用文件上下文菜单条目的功能,如下所示:

"C:\Program Files (x86)\...\program.exe" /Enqueue "%1"

如何将这些参数传递给流程构建器?

我已经尝试了以下方法,但都没有奏效:

p.command("C:\\Program Files (x86)\\...\\program.exe","/Enqueue","%1",next.getAbsolutePath());
p.command("C:\\Program Files (x86)\\...\\program.exe","Enqueue","%1",next.getAbsolutePath());
p.command("C:\\Program Files (x86)\\...\\program.exe","Enqueue","\"%1\"",next.getAbsolutePath());
p.command("C:\\Program Files (x86)\\...\\program.exe","/Enqueue","\"%1\"",next.getAbsolutePath());

在这种情况下,“不工作”意味着程序已启动,但没有任何反应(文件甚至没有打开)。

如果我按以下顺序切换它们:(程序、文件、参数),则文件会正确打开,但其他参数什么也不做,就好像它们根本不存在一样。

将这些参数转换为 ProcessBuilder 命令的正确方法是什么?

【问题讨论】:

  • 您需要用 String 替换值 %1 来代替您想要传递的任何内容。您还需要将String 分解为一个数组,以便每个命令/参数都是一个单独的元素
  • 好的,所以程序是一个带有队列的媒体播放器,所以我假设 %1 应该是文件名。我现在尝试了这个版本: p.command("C:\\Program Files (x86)\\...\\program.exe", "Enqueue", next.getAbsolutePath());但它仍然只打开文件,没有别的......

标签: java command parameter-passing contextmenu processbuilder


【解决方案1】:

您需要做的第一件事是将"C:\Program Files (x86)\...\program.exe" /Enqueue "%1" 变成[C:\Program Files (x86)\...\program.exe, /Enqueue, %1] 的数组,否则ProcessBuilder 将尝试将整个String 作为单个命令执行,这确实不是您想要的。

也许是……

String cmd = "\"C:\\Program Files (x86)\\...\\program.exe\" /Enqueue \"%1\"";
StringBuilder sb = new StringBuilder(cmd);
List<String> commands = new ArrayList<>(10);
while (sb.length() > 0) {
    if (sb.charAt(0) == '"') {
        int nextIndex = sb.indexOf("\"", 1);
        if (nextIndex < 0) {
            nextIndex = sb.length();
        } else {
            nextIndex++;
        }
        commands.add(sb.substring(1, nextIndex).replace("\"", ""));
        sb.delete(0, nextIndex);
    } else if (sb.charAt(0) == ' ') {
        if (sb.length() > 1 && sb.charAt(1) != '"') {
            int nextIndex = sb.indexOf(" ", 1);
            if (nextIndex < 0) {
                nextIndex = sb.length();
            }
            commands.add(sb.substring(1, nextIndex));
            sb.delete(0, nextIndex);
        } else {
            sb.delete(0, 1);
        }
    }
}
System.out.println(commands);

哪个会打印...

[C:\Program Files (x86)\...\program.exe, /Enqueue, %1]

您可能可以使用一个非常简洁的正则表达式来帮助解决这个问题,但这或多或少可以完成工作。

接下来,您要将%1 替换为您要打开的文件。现在,您可以在之前的代码中执行此操作,这样会更高效,但出于演示目的...

String[] parameters = {"Hello kitty"};
for (int index = 0; index < commands.size(); index++) {
    String value = commands.get(index);
    if (value.startsWith("%")) {
        int parameter = Integer.parseInt(value.substring(1)) - 1;
        if (parameter < parameters.length) {
            commands.set(index, parameters[parameter]);
        }
        // You might want to think about what you want to do if you have
        // more parameter marks then you do have actual parameter values
    }
}
System.out.println(commands);

打印出来的...

[C:\Program Files (x86)\...\program.exe, /Enqueue, Hello kitty]

您现在可以将其传递给ProcessBuilder,例如...

ProcessBuilder pb = new ProcessBuilder(commands);

现在,您可以在代码中的许多不同点以许多不同的方式执行 String 替换,这只是其中的一个示例

【讨论】:

  • 好的,这一切都说得通,不幸的是,软件仍然不能正常运行……但我开始认为问题不在于代码,而在于软件本身。我现在注意到直接从上下文菜单调用命令也不能正常工作......所以我认为java代码完全符合实际上下文菜单条目的作用(这显然不多......)。我要报告这个问题,否则谢谢你的帮助!