问题通过NSTask启动X11应用程序

时间:2013-03-27 00:52:09

标签: objective-c macos unix pygtk

我的应用程序使用NSTask执行shell脚本,其中一个脚本启动X11应用程序(特别是meld)。

我希望这可行:

#!/bin/bash
source ~/.profile                      # setup $PATH/etc
meld .

但它失败了:

gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
Traceback (most recent call last):
  File "/usr/local/bin/meld", line 132, in <module>
    gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
AttributeError: 'NoneType' object has no attribute 'append_search_path'

作为概念验证,我将脚本更改为此,这非常有效:

#!/usr/bin/ruby

exec 'osascript -e \'tell app "Terminal" to do script "meld ' + Dir.pwd + '" in front window\''

有没有人导致这个问题?这是我执行shell脚本的代码:

NSTask *task = [[NSTask alloc] init];
task.launchPath = self.scriptURL.path;
task.standardOutput = [NSPipe pipe];
task.currentDirectoryPath = workingDirectoryURL.path;

[task launch];

3 个答案:

答案 0 :(得分:2)

X11应用程序使用DISPLAY环境变量了解显示服务器的地址。

在OS X上,出于安全原因,DISPLAY值是随机的,因此您无法对其进行硬编码,正如您所注意到的那样。相反,有一个launchd代理告诉launchd在启动进程时设置DISPLAY。

在launchd和meld之间,DISPLAY的值被删除或覆盖。你的工作是找出原因。

  1. 确保launchd代理程序正在运行。运行launchctl list并查找org.macosforge.xquartz.startx。由于meld正在使用Terminal.app,因此这部分可能是正确的。
  2. 确保在您的应用中设置了DISPLAY。它应该列在[NSProcessInfo processInfo].environment
  3. 确保在您启动的NSTask中设置了DISPLAY。尝试使用NSTask运行/usr/bin/env,并确保在其输出中显示DISPLAY。
  4. 确保在您运行的脚本中设置了DISPLAY。在采购〜/ .profile之前和之后尝试echo $DISPLAY。 (有时.profile本身会将DISPLAY重写为不正确的值,因为在其他操作系统上这有时是正确的。)
  5. 编辑:这是我用来将GUI应用程序中的DISPLAY复制到shell脚本的代码:

    NSTask *task = ...
    task.environment = [NSProcessInfo processInfo].environment;
    [task.launch];
    

答案 1 :(得分:1)

更改脚本以显示环境变量并将“工作”与“不工作”进行比较。

在不同的执行模型中如何初始化shell之间存在细微差别。几乎可以肯定,环境是您问题的根源。

答案 2 :(得分:0)

看看man launchctl

launchctl submit ... -p / usr / local / bin / meld - 。

启动启动工作;这将为您设置某些环境变量,这些变量是每个用户会话的一部分。