标题类型说明了一切:
我想知道是否有任何_NSWasLaunchedFromFinder
类型的API或钩子,OS / XC程序(int main(int argc, char* argv[])
种类)可以用来确定它是否是由用户点击Finder中的可执行文件,如果它是通过更传统的路径运行(比如输入终端)。
答案 0 :(得分:2)
如果您正在谈论普通命令行实用程序 - 无法确定它是从Finder还是在终端中启动,因为Finder将启动终端,然后在其中执行您的程序。
但有一个解决方案。我宁愿称之为解决方法。您可以使用bundle包装可执行文件,创建简单脚本(让我们称之为finderLauncher
),这将使用一些额外的命令行参数(例如-launchedFromFinder
)启动实际可执行文件。别忘了让它可执行。而不是在Info.plist文件中将finderLauncher
设置为CFBundleExecutable
值
现在,在Finder中,用户只会看到您的软件包,通过单击它,您的实际可执行文件将通过finderLauncher
传递指定的命令行参数启动。在终端中使用open
命令也会出现相同的行为。
通过从终端直接启动,将没有-launchedFromFinder参数(当然如果用户不直接传递它)。
附:通过直接在Info.plist中指定命令行参数会容易得多,但我在Information Property List Key Reference中找不到这样的键,尽管代理/守护进程有这样的键。
答案 1 :(得分:0)
方法1 :: 您可以使用NSGetExecutablePath
这里是对它的开发引用:: Mac Developer Library
_NSGetExecutablePath()将主可执行文件的路径复制到缓冲区buf中。 bufsize参数最初应该是缓冲区的大小。如果路径已成功复制,则此函数返回0,并且* bufsize保持不变。如果缓冲区不够大,则返回-1,并且* bufsize设置为所需的大小。请注意_NSGetExecutablePath()将返回"路径"对于exe- 可切割的不是真正的路径"到可执行文件。也就是说,路径可以是符号链接而不是真实的 文件。对于深度目录,所需的总bufsize可能超过MAXPATHLEN。
方法2 :: 使用AppleScript
您可以使用AppleScript通过以下脚本::
查找当前打开的应用程序tell application "Finder"
set appPath to my getFrontAppPath()
set AppleScript's text item delimiters to {":"}
set currentApp to text item -2 of appPath
say currentApp
end tell
on getFrontAppPath()
set frontAppPath to (path to frontmost application) as text
set myPath to (path to me) as text
if frontAppPath is myPath then
try
tell application "Finder" to set bundleID to id of file myPath
tell application "System Events" to set visible of (first process whose bundle identifier is bundleID) to false
-- we need to delay because it takes time for the process to hide
-- I noticed this when running the code as an application from the applescript menu bar item
set inTime to current date
repeat
set frontAppPath to (path to frontmost application) as text
if frontAppPath is not myPath then exit repeat
if (current date) - inTime is greater than 2 then exit repeat
end repeat
end try
end if
return frontAppPath
end getFrontAppPath
那应该是你上次打开的应用程序,无论是终端还是Finder :)
对于Finder,您会收到回复::" Macintosh HD:系统:库:CoreServices:Finder.app:"
对于终端::" Macintosh HD:应用程序:实用程序:Terminal.app:"
答案 2 :(得分:0)
Get the Parent Process ID。然后浏览其Process Status以获取其PPID,递归到Finder.app或init。
找到Finder.app的终端祖先后,您可以查看其开始时间及其参数(请参阅-o
中的-O
和man ps
选项:您的关键字应该包括args
和start
):如果终端进程在您的程序开始时间附近开始并且参数包含您的程序名称,则您知道它已由Finder.app启动。
也许你可以忽略时间,只是寻找终端的论点。
答案 3 :(得分:0)
您可以采用反向逻辑并使用isatty。
if (isatty(1)) printf("Launched in a terminal\n");
else printf("Launched by clicking something\n");
这只是确定stdout是否为tty。如果你从程序,图标,菜单等启动它...它将是错误的。另外,如果你想知道X服务器是否正在运行并且它是从终端模拟器启动的,你可以使用getenv(“DISPLAY”),它在X启动时设置(所以如果从控制台运行它将是NULL)
答案 4 :(得分:0)
// when the user doubleclicks your program it will be started with a -psn_ parameter
if (argc >= 2 && (strncmp(argv[1], "-psn_", 5) == 0)) {
InfoLogWithClient(L"Init", L"Program %d cannot be started with double-click!", getpid());
return EX_USAGE;
}