在 mac 中发生锁定时如何以编程方式 运行 执行任务
how to programatically run a task when a logout occurs in mac
当 Mac
中发生注销事件时,我正在尝试 运行 shell 命令
logoutNotificationCenter.notificationCenter.addObserver(self, selector: #selector(AppDelegate.logOut),name:NSWorkspace.willPowerOffNotification, object: nil)
内部注销我正在使用 运行 shell 命令
func shell(path:String,commandargs: [String]) -> Bool
{
var ret : Bool = false
let task = Process()
task.launchPath = path
task.arguments = commandargs
task.launch()
task.waitUntilExit()
if !task.isRunning {
let status = task.terminationStatus
if status == 0 {
ret = true
} else {
ret = false
}
}
return ret
}
虽然我的通知是由 shell 触发的,但不是 运行 ,甚至在此之前我的系统就已经关闭了。有没有一种方法可以在我的 shell 命令执行之前停止注销。
我再次阅读了您的问题,问题是 applicationShouldTerminate(_:)
在 发送 NSWorkspace.willPowerOffNotification
之前被调用 。这意味着你不知道发生了什么。
然后我意识到我们得到了kAEQuitReason
。很好奇它是否仍然有效并且确实有效。下面的例子。以适合您需要的方式修改它。
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet var window: NSWindow!
private var logoutTaskLaunched = false
private func launchLogoutTask() {
assert(!logoutTaskLaunched, "Logout task was already launched")
let task = Process()
task.executableURL = URL(fileURLWithPath: "/bin/sleep")
task.arguments = ["5"]
task.terminationHandler = { task in
if task.terminationStatus == 0 {
print("Logout task - success")
DispatchQueue.main.async {
NSApp.reply(toApplicationShouldTerminate: true)
}
} else {
print("Logout task - failed")
DispatchQueue.main.async { [weak self] in
NSApp.reply(toApplicationShouldTerminate: false)
self?.logoutTaskLaunched = false
}
}
}
do {
try task.run()
logoutTaskLaunched = true
print("Logout task - Sleeping for 5s")
}
catch {
print("Logout task - failed to launch task: \(error)")
NSApp.reply(toApplicationShouldTerminate: false)
}
}
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
let reason = NSAppleEventManager.shared()
.currentAppleEvent?
.attributeDescriptor(forKeyword: kAEQuitReason)
switch reason?.enumCodeValue {
case kAELogOut, kAEReallyLogOut:
print("Logout")
if !logoutTaskLaunched {
launchLogoutTask()
}
return .terminateLater
case kAERestart, kAEShowRestartDialog:
print("Restart")
return .terminateNow
case kAEShutDown, kAEShowShutdownDialog:
print("Shutdown")
return .terminateNow
case 0:
// `enumCodeValue` docs:
//
// The contents of the descriptor, as an enumeration type,
// or 0 if an error occurs.
print("We don't know")
return .terminateNow
default:
print("Cmd-Q, Quit menu item, ...")
return .terminateNow
}
}
}
当 Mac
中发生注销事件时,我正在尝试 运行 shell 命令 logoutNotificationCenter.notificationCenter.addObserver(self, selector: #selector(AppDelegate.logOut),name:NSWorkspace.willPowerOffNotification, object: nil)
内部注销我正在使用 运行 shell 命令
func shell(path:String,commandargs: [String]) -> Bool
{
var ret : Bool = false
let task = Process()
task.launchPath = path
task.arguments = commandargs
task.launch()
task.waitUntilExit()
if !task.isRunning {
let status = task.terminationStatus
if status == 0 {
ret = true
} else {
ret = false
}
}
return ret
}
虽然我的通知是由 shell 触发的,但不是 运行 ,甚至在此之前我的系统就已经关闭了。有没有一种方法可以在我的 shell 命令执行之前停止注销。
我再次阅读了您的问题,问题是 applicationShouldTerminate(_:)
在 发送 NSWorkspace.willPowerOffNotification
之前被调用 。这意味着你不知道发生了什么。
然后我意识到我们得到了kAEQuitReason
。很好奇它是否仍然有效并且确实有效。下面的例子。以适合您需要的方式修改它。
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet var window: NSWindow!
private var logoutTaskLaunched = false
private func launchLogoutTask() {
assert(!logoutTaskLaunched, "Logout task was already launched")
let task = Process()
task.executableURL = URL(fileURLWithPath: "/bin/sleep")
task.arguments = ["5"]
task.terminationHandler = { task in
if task.terminationStatus == 0 {
print("Logout task - success")
DispatchQueue.main.async {
NSApp.reply(toApplicationShouldTerminate: true)
}
} else {
print("Logout task - failed")
DispatchQueue.main.async { [weak self] in
NSApp.reply(toApplicationShouldTerminate: false)
self?.logoutTaskLaunched = false
}
}
}
do {
try task.run()
logoutTaskLaunched = true
print("Logout task - Sleeping for 5s")
}
catch {
print("Logout task - failed to launch task: \(error)")
NSApp.reply(toApplicationShouldTerminate: false)
}
}
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
let reason = NSAppleEventManager.shared()
.currentAppleEvent?
.attributeDescriptor(forKeyword: kAEQuitReason)
switch reason?.enumCodeValue {
case kAELogOut, kAEReallyLogOut:
print("Logout")
if !logoutTaskLaunched {
launchLogoutTask()
}
return .terminateLater
case kAERestart, kAEShowRestartDialog:
print("Restart")
return .terminateNow
case kAEShutDown, kAEShowShutdownDialog:
print("Shutdown")
return .terminateNow
case 0:
// `enumCodeValue` docs:
//
// The contents of the descriptor, as an enumeration type,
// or 0 if an error occurs.
print("We don't know")
return .terminateNow
default:
print("Cmd-Q, Quit menu item, ...")
return .terminateNow
}
}
}