如何在Mac上从Java启动另一个应用程序

如何在Mac上从Java启动另一个应用程序,java,macos,swt,exec,Java,Macos,Swt,Exec,我写的在Windows上运行良好的代码在Mac上不起作用。 我所说的简短形式是: Runtime.getRuntime().exec (String ["/Applications/CM Battle for Normandy/CM Battle for Normandy.app" "2vs2 White Manor 072.ema"], null, "/Applications/CM Battle for Normandy/"); 我尝试运行的软件没有设置与.ema文件的文件关联(如果您好奇

我写的在Windows上运行良好的代码在Mac上不起作用。 我所说的简短形式是:

Runtime.getRuntime().exec (String ["/Applications/CM Battle for Normandy/CM Battle for Normandy.app" "2vs2 White Manor 072.ema"], null, "/Applications/CM Battle for Normandy/");
我尝试运行的软件没有设置与.ema文件的文件关联(如果您好奇,这是一个游戏)

我的代码如下所示:

    private void launchGameProgram (PBEMGame selectedGame) {
    if (selectedGame == null)
        return; // no work to do

    InstalledProgram program = selectedGame.playedWith ();
    if (program == null)
        return; // no work to do

    try {
        Vector<String> command = new Vector<String> ();
        command.add (program.getExeFile ().getAbsolutePath ());
        if (selectedGame.getLastTurn () != null  &&  selectedGame.getLastTurn ().getTurnFile () != null)  {
            //  Add the turn file name to the command
            command.add (selectedGame.getLastTurn ().getTurnFile ().getName ());
        }
        GUIApplicationPolicy.getLog ().log ("WTII testing: About to launch: " + command.toString () + " from: " + program.getExeFile ().getParentFile ());
        Runtime.getRuntime ().exec (command.toArray (new String[command.size ()]), null, program.getExeFile ().getParentFile ());
    } catch (IOException exception) {
        GUIApplicationPolicy.getLog ().log (exception);
        exception.printStackTrace();
    }
}
private void launchGameProgram(PBEMGame selectedGame){
如果(selectedGame==null)
return;//没有要做的工作
InstalledProgram=selectedGame.playedWith();
if(程序==null)
return;//没有要做的工作
试一试{
Vector命令=新向量();
command.add(program.getExeFile().getAbsolutePath());
if(selectedGame.getLastTurn()!=null&&selectedGame.getLastTurn().getTurnFile()!=null){
//将turn文件名添加到命令中
command.add(selectedGame.getLastTurn().getTurnFile().getName());
}
GUIApplicationPolicy.getLog().log(“WTII测试:即将启动:“+command.toString()+”来自:“+program.getExeFile().getParentFile()”);
Runtime.getRuntime().exec(command.toArray(新字符串[command.size()]),null,program.getExeFile().getParentFile());
}捕获(IOException异常){
GUIApplicationPolicy.getLog().log(异常);
异常。printStackTrace();
}
}
这将在日志中生成以下内容:

!Entry: 2013/10/02 23:08:33.017
!Message: WTII testing: About to launch: [/Applications/CM Battle for Normandy/CM Battle for Normandy.app, 2vs2 White Manor 072.ema] from: /Applications/CM Battle for Normandy

!Entry: 2013/10/02 23:08:33.023
!Exception: Cannot run program "/Applications/CM Battle for Normandy/CM Battle for Normandy.app" (in directory "/Applications/CM Battle for Normandy"): error=13, Permission denied
!Stack: java.io.IOException: Cannot run program "/Applications/CM Battle for Normandy/CM Battle for Normandy.app" (in directory "/Applications/CM Battle for Normandy"): error=13, Permission denied
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1041)
    at java.lang.Runtime.exec(Runtime.java:617)
    at com.lesliesoftware.whoseturnisit.WhoseTurnIsIt.launchGameProgram(Unknown Source)
    at com.lesliesoftware.whoseturnisit.WhoseTurnIsIt.access$3100(Unknown Source)
    at com.lesliesoftware.whoseturnisit.WhoseTurnIsIt$LaunchSelectedGameProgram.widgetSelected(Unknown Source)
    at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3776)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1367)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1390)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1375)
    at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1187)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3622)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3277)
    at com.lesliesoftware.whoseturnisit.WhoseTurnIsIt.main(Unknown Source)
Caused by: java.io.IOException: error=13, Permission denied
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:135)
    at java.lang.ProcessImpl.start(ProcessImpl.java:130)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1022)
    ... 14 more
!条目:2013/10/02 23:08:33.017
!消息:WTII测试:即将启动:[/Applications/CM Battle for Normandy/CM Battle for Normandy.app,2vs2 White Manor 072.ema]发件人:/Applications/CM Battle for Normandy
!条目:2013/10/02 23:08:33.023
!异常:无法运行程序“/Applications/CM-Battle for Normandy/CM-Battle for Normandy.app”(目录“/Applications/CM-Battle for Normandy”):错误=13,权限被拒绝
!堆栈:java.io.IOException:无法运行程序“/Applications/CM Battle for Normandy/CM Battle for Normandy.app”(目录中“/Applications/CM Battle for Normandy”):错误=13,权限被拒绝
位于java.lang.ProcessBuilder.start(ProcessBuilder.java:1041)
位于java.lang.Runtime.exec(Runtime.java:617)
位于com.lesliesoftware.whoseturnisit.whoseturnisit.launchGameProgram(未知源)
访问com.lesliesoftware.whoseturnisit.whoseturnisit.access$3100(未知来源)
在com.lesliesoftware.whoseturnist.whoseturnist$LaunchSelectedGameProgram.widgetSelected(未知源)
位于org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
位于org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
位于org.eclipse.swt.widgets.Display.sendEvent(Display.java:3776)
位于org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1367)
位于org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1390)
位于org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1375)
位于org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1187)
位于org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3622)
在org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3277)上
位于com.lesliesoftware.whoseturnisit.whoseturnisit.main(未知源)
原因:java.io.IOException:错误=13,权限被拒绝
位于java.lang.UNIXProcess.forkAndExec(本机方法)
位于java.lang.UNIXProcess(UNIXProcess.java:135)
在java.lang.ProcessImpl.start(ProcessImpl.java:130)
位于java.lang.ProcessBuilder.start(ProcessBuilder.java:1022)
... 14多
任何帮助或指导都将不胜感激。

您正在尝试执行“CM Battle for Normandy.app”,这是一个文件夹(是的,我知道扩展名为.app可能会误导您)。您要做的是在该文件夹中找到一个二进制文件并执行它。通常在该文件夹中有一个目录文件夹,其中有一个MacOS文件夹,该文件夹中应该有一个可执行文件(可能是“诺曼底CM之战”)

您可以通过终端或查找器找到它

所以我的任务是改变:

"/Applications/CM Battle for Normandy/CM Battle for Normandy.app"

但可能会略有不同。它没有像Windows那样的扩展名(即.exe或smth),但这是因为MacOS是Unix类型的系统。

试试这个

Runtime.getRuntime().exec (String ["open /Applications/CM Battle for Normandy/CM Battle for Normandy.app" "--args" "2vs2 White Manor 072.ema"], null, "/Applications/CM Battle for Normandy/")
更新:与伊恩讨论后

Runtime.getRuntime().exec (String ["open" "/Applications/CM Battle for Normandy/CM Battle for Normandy.app" "--args" "2vs2 White Manor 072.ema"], null, "/Applications/CM Battle for Normandy/")

这是从命令行运行的吗?我看到了一个命令变量,但我没有看到任何关于它实际是/做什么的上下文。您可能需要为任何命令添加一个“sudo”前缀(假设它在终端中)。我只是从权限错误中推断出来的


另外,我看到一个“getExeFile”。也许我误解了这一点,但为什么你要在MacOS上寻找一个.exe?再一次,我可能只是误解了这个代码。无论如何,我希望这有助于或至少有助于你的大脑运动。

不知道如何回答“这是从命令行运行的吗?”。我没有命令行,但我正在尝试启动另一个应用程序,在Windows上,这些参数将与命令行窗口中使用的参数相同。getExeFile是我为自己的私有类编写的方法,最初是在Windows上编写的。我从来没有想到,在mac上,可执行的东西(因为没有更好的词)将是一个目录而不是一个文件。因此,名称只是一个工件,返回的实际文件对象是windows上的xxx.exe和mac上的xxx.app。@IanLeslie“那可执行的东西”是一个二进制文件,mac上有应用程序的二进制文件,正如我在AnswerUnderstand@MateuszDymczyk中发布的,我正在跟进你的建议(连同@vidit的公开建议)。我的意思是,从最终用户的角度来看,Mac将.app文件夹显示为可选择的可执行实体。这与任何其他可执行实体为文件的操作系统非常不同。有趣的是,open在这种情况下做了什么?@IanLeslie-
open
是用于执行应用程序的Mac命令。请尝试
open/Applications/CM诺曼底之战/CM诺曼底之战.app--args 2vs2 White Manor 072.ema
from
Runtime.getRuntime().exec (String ["open" "/Applications/CM Battle for Normandy/CM Battle for Normandy.app" "--args" "2vs2 White Manor 072.ema"], null, "/Applications/CM Battle for Normandy/")