经过一段时间后,我想终止一些应用程序的执行。我正在对NSWorkspace的runningApplications进行轮询,因为它缺少可以观察到的内容(如果应用程序正在运行,它会通知什么吗?)
我的问题是,应用程序有时只会被终止,有时会在应该关闭的时间(根据内部计时器)之后几秒钟完成,有时甚至根本不会终止!
我尝试使用终止方法和forceTerminate方法。
在代码片段中,_apps_是包含应用程序名称的字符串向量。它由另一个线程定期更新,并在运行以下代码之前接收其数据。它们都在_es_handler_block_t中运行
NSArray<NSRunningApplication *> *running_apps = [NSWorkspace sharedWorkspace].runningApplications;
for (const auto &app_ : apps_) {
//std::cout << app_ << "\n";
for (NSRunningApplication *app in running_apps) {
if ([[NSString stringWithUTF8String:app_.c_str()] isEqualToString:[app.executableURL lastPathComponent]] ) {
std::string app_name = [[app.executableURL absoluteString] UTF8String];
std::cout << "Terminating app " << app_name << "\n";
bool res_f = [app forceTerminate];
bool res_t = [app terminate];
LOG_DBG("Force terminate: %d", res_f);
LOG_DBG("Terminate: %d", res_t);
break;
}
}
}我在runningApplications文档中看到,“只有在主运行循环以公共模式运行时,此属性才会更改”。什么意思?
我认为这与运行应用程序的轮询有关,因为在上面的代码中插入一个断点(在if检查之前),然后恢复执行会立即杀死本来仍在运行的应用程序。
我没有阻止主要功能。我只有一个端点安全类作为框架,网络是在其他线程上完成的,我使用return和NSApplicationMain(argc, argv);
有什么问题吗?谢谢。
编辑:我正在利用Cocoa创建一个只显示在系统托盘中并且具有根权限的代理。使用终结点安全框架( Endpoint Security )成功地阻止了应用程序的启动,但我没有找到一种可靠的方法来杀死已经在运行的应用程序,这些应用程序每次都能工作。
稍后编辑:我设法向[[NSWorkspace sharedWorkspace] notificationCenter]添加了一个观察者,但是对于正在运行的应用程序,我应该订阅什么通知呢?我尝试过隐藏,但如果用户只点击红色窗口按钮,只有当用户将应用程序隐藏在码头上时,它就无法工作。但是我仍然想关闭它,即使用户和运行中的应用程序之间没有交互。
发布于 2020-06-01 00:10:26
在macOS上可靠地终止应用程序取决于许多因素,例如:
例如,您的应用程序可能被允许终止一个应用程序,但是,例如,如果您使用像下面这样的plist来终止launchd用KeepAlive命令启动的进程:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.bundleidentifierOf.AnUnquitabbleApp</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/the/AnUnquitableApp</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>你会大吃一惊,因为当你试图这么做的时候,launchd会立即重新启动它,看起来这款应用程序似乎没有被杀,但它确实是。您可以看到,应用程序是重新启动,当它的PID变化,每次你试图杀死它。
您可以使用以下命令来检查:
ps -ax在终端中列出在Mac上运行的所有进程。如果您想知道应用程序是否正在运行,请使用:
ps -ax | grep "AnUnquitableAppNameHere"然后,您可以使用它的PID与
kill <PID>这将帮助您确定哪些应用程序可以使用简单的退出信号来杀死,哪些应用程序需要使用更强的信号来终止它们,而这些应用程序是不可缺少的,因为要杀死这些应用程序需要您的应用程序可能没有的特权或权利。阅读ps和kill的手册页,了解更多关于目标应用程序的信息。
在macOS上有许多其他的方法来获得持久性,如果您想了解如何可靠地退出应用程序,首先需要了解它们是如何获得持久性的。
例如,如果用户拥有管理/超级用户权限,则可以通过在/Library/LaunchDaemons中安装守护进程来获得持久性。如果您的应用程序没有根权限,则不太可能终止该进程。
除了launchd plist之外,应用程序保持持久性的另一种方法是,例如,有一个后台应用程序,一旦主应用程序被迫退出,它就会重新启动。一个例子是,如果您使用kill来杀死最新版本的Microsoft Word,您将看到它将由这样一个助手重新启动,该助手会抱怨Word被迫退出。
杀死一个应用程序最好的方法实际上是发送一个退出苹果事件,这是我通常做的。
我不想让你灰心丧气,但你想要达到的目标似乎比最初看起来更困难。即使你成功了,也要记住,用户可能会杀了你的应用程序,这会挫败你想要达到的目标,除非它被一个启动程序或其他形式的坚持所维持。
现在,如果您想观察哪些应用程序在没有投票的情况下被杀死或启动,我绝对建议您阅读TN2050。
现在回答你的具体问题:
“只有在主运行循环以公共模式运行时,此属性才会更改”
这意味着您需要一个运行循环来更新NSRunningApplication。如果您有一个GUI应用程序,那么已经为您安装了这样一个循环。如果您的应用程序是一个CLI,那么这是没有安装的,您需要自己安装这样一个运行循环。如果您使用的是Objective,那么您可以按照这个问题中的建议来做。
因此,你想要达到的目标有很多警告,你需要在继续之前意识到它们。
https://stackoverflow.com/questions/62118302
复制相似问题