如何判断进程在 OSX 上是否有图形界面?

发布于 2024-12-10 21:54:25 字数 367 浏览 0 评论 0原文

无论如何,我们可以识别进程是否有用户界面吗?任何涉及在屏幕上绘图的东西。

我查看了这个问题,但它没有给出正确的答案。我在这个过程中。是否有一些我可以查询的API,或者一些技术?

编辑:我在进程内部,我正在进行代码注入。我希望非 GUI 应用程序的行为与 GUI 应用程序不同。我无法使用 CFBundleGetValueForInfoDictionaryKey() 或 NSApplicationMain,因为我想保持注入模块轻便,因此我无法链接到这些框架。

Is there anyway, we can identify if the process has user interface? Anything which deals with drawing on screen.

I looked at this question, but it does not give proper answer. I am inside the process. Is there some api where i can query, or some technique?

EDIT: I am inside the process, I am doing code injection. I want to behave different for non gui apps than gui ones. I cannot use CFBundleGetValueForInfoDictionaryKey() or NSApplicationMain as I want to keep injection module light and thus I cannot link against these frameworks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁与争疯 2024-12-17 21:54:25

这在很大程度上取决于您所说的“具有图形界面”的含义。您的意思是“正在显示一个窗口”吗?或者“有一个停靠图标?”或者“可以访问 Aqua 上下文,以便它可以根据需要显示一个窗口?”或者“与 AppKit 链接?”

没有停靠图标的应用程序包会将 Info.plistLSUIElement 设置为“1”。您可以使用 CFBundleGetValueForInfoDictionaryKey() 来获取它(如果您使用的是 Objective-C,则使用等效的 NSBundle)。这并不意味着应用程序没有 GUI,而是意味着它不会显示在扩展坞中。许多 LSUIElement 应用都有状态项 UI。

您还可以使用 CFBundleCopyBundleURL() 等检查您是否确实拥有 Info.plist。如果您没有 Info.plist,那么您很可能不会成为“类似 GUI”的程序。 (尽管如此,没有这个也可以生成 GUI)。

您可以使用弱链接来测试 AppKit:

if (NSApplicationMain != NULL) {
  // We're linked with AppKit
}

这是一个相当好的指标,表明您将拥有一个 UI。但它不会捕获较旧的 Carbon 应用程序。

关于“我在这个过程中”的含义的更多背景知识将会有所帮助。我假设您是一个框架,并且希望 GUI 应用程序的行为与非 GUI 应用程序的行为不同?


为了检测能够在屏幕上绘图的应用程序,我会检查 CoreGraphics 是否已链接。这仅适用于自 10.3 以来构建的程序,但应该相当准确(我相信旧的 QuickDraw 应用程序仍然链接 10.3+ 中的 Core Graphics,但我没有方便检查的工具)。可能最好的方法是进行 弱链接检查CGColorCreate() 因为它已经存在了很长时间并且不太可能消失:

extern CGColorRef CGColorCreate(CGColorSpaceRef space, const CGFloat components[]) 
    __attribute__((weak_import));

...
if (CGColorCreate != NULL) {
  // Linked with CoreGraphics. Probably a GUI

当然,事物可以与 CoreGraphics 链接并能够在屏幕上,但从未实际在屏幕上绘制。它们可能与 CoreGraphics 链接以进行图像处理。查找 ApplicationServices 可能会更准确。您可以针对 NULL 测试 ApplicationServicesVersionNumber,但这没有记录。

这不会捕获 X 应用程序,因为从技术上讲它们并不在屏幕上绘制。他们将命令发送到 X11.app,这是一个 GUI。您是否认为 /usr/X11/bin/xterm 是用于此目的的 GUI? /usr/X11/bin/xeyes?

据我所知,在任何应用程序中都没有明确表示“我在屏幕上画画”的特定标志。在屏幕上绘图不需要预先声明。在屏幕上绘制的应用程序不必每次运行时都这样做。通常不可见的应用程序可能会选择或偶尔创建状态项。很难想出一个包含 GrowlHelperApp.app、Pages.app 和 /usr/X11/bin/xeyes 的单一描述。

This depends heavily on what you mean by "has a graphical interface." Do you mean, "is displaying a window?" Or "has a dock icon?" Or "has access to the Aqua context such that it could display a window if it wanted to?" Or "is linked with AppKit?"

An app bundle that does not have a dock icon will have the Info.plist key LSUIElement set to "1". You can fetch this using CFBundleGetValueForInfoDictionaryKey() (or the NSBundle equivalent if you're in Objective-C). This does not mean the application has no GUI, but does mean it won't show up in the dock. Many LSUIElement apps have a status item UI.

You can also check that you actually have an Info.plist at all using CFBundleCopyBundleURL() or the like. If you don't have an Info.plist, then you're not going to be a "GUI-like" program in all likelihood. (Though again, it's possible to generate GUIs without this).

You can use weak linking to test for AppKit:

if (NSApplicationMain != NULL) {
  // We're linked with AppKit
}

That's a fairly good indicator that you're going to have a UI. But it won't catch older Carbon apps.

Some more background on what you mean by "I am inside the process" would be helpful. I assume you're a framework and want to behave differently for GUI apps than for non-GUI apps?


To detect an application capable of drawing on the screen, I would check for whether CoreGraphics is linked. That'll only work for programs built since 10.3, but should be fairly accurate (I believe that old QuickDraw apps still link Core Graphics in 10.3+, but I don't have one handy to check). Probably the best way is to do a weak linking check against CGColorCreate() since it's been around for a long time and is unlikely to ever go away:

extern CGColorRef CGColorCreate(CGColorSpaceRef space, const CGFloat components[]) 
    __attribute__((weak_import));

...
if (CGColorCreate != NULL) {
  // Linked with CoreGraphics. Probably a GUI

Of course things can link with CoreGraphics and be capable of drawing on the screen, but never actually draw on the screen. They might link with CoreGraphics in order to do image processing. It might be more accurate by looking for ApplicationServices. You could test ApplicationServicesVersionNumber against NULL, but that's not documented.

This will not catch X apps, since they don't technically draw on the screen. They send commands to X11.app, which is a GUI. Do you consider /usr/X11/bin/xterm a GUI for this purpose? /usr/X11/bin/xeyes?

There is no particular flag I'm aware of in any app that says unambiguously "I draw on the screen." Drawing on the screen is not something you need to pre-declare. Apps that draw on the screen don't have to do so every time they run. Apps that are generally invisible might optionally or occasionally create a status item. It's hard to come up with a single description that includes GrowlHelperApp.app, Pages.app, and /usr/X11/bin/xeyes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文