代码之家  ›  专栏  ›  技术社区  ›  YanivH

从未调用NSWorkspaceWillPowerOffNotification

  •  4
  • YanivH  · 技术社区  · 7 年前

    我试图在后台进程中运行一个程序,该程序将注册系统中的每个关闭事件。

    通过注册到NSWorkspaceWillPowerOffNotification来完成此操作,如下所示:

    #import <AppKit/AppKit.h>
    
    @interface ShutDownHandler : NSObject <NSApplicationDelegate>
    
    - (void)computerWillShutDownNotification:(NSNotification *)notification;
    
    @end
    
    
    int main(int argc, char* argv[]) {
        NSNotificationCenter *notCenter;
    
        notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
    
        ShutDownHandler* sdh = [ShutDownHandler new];
    
        [NSApplication sharedApplication].delegate = sdh;
    
        [notCenter addObserver:sdh
                      selector:@selector(computerWillShutDownNotification:)
                          name:NSWorkspaceWillPowerOffNotification
                        object:nil];
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            [[NSFileManager defaultManager] createFileAtPath:@"./output.txt" contents:nil attributes:nil];
        });
    
        [[NSRunLoop currentRunLoop] run];
    
        return 0;
    }
    
    
    @implementation ShutDownHandler
    
    - (void)computerWillShutDownNotification:(NSNotification *)notification {
        NSFileHandle* file = [NSFileHandle fileHandleForUpdatingAtPath: @"./output.txt"];
        [file seekToEndOfFile];
    
        NSDateFormatter* fmt = [NSDateFormatter new];
        [fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        NSDate* current = [NSDate date];
    
        NSString* dateStr = [fmt stringFromDate:current];
        [dateStr writeToFile:@"./output.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
    
    - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
    {
        return NSTerminateCancel;
    }
    
    @end
    

    由于某些我无法理解的原因,从未调用过NSWorkspaceWillPowerOffNotification处理程序!

    还将以下内容添加到我的。plist:

    <key>NSSupportsSuddenTermination</key>
    <false/>
    

    但在关闭我的系统时,仍然没有注册通知。

    知道为什么吗??

    3 回复  |  直到 7 年前
        1
  •  4
  •   YanivH    6 年前

    供将来参考:

    我无法注册上述活动,并看到它火灾。

    apple open-source power management

    在这里,您可以看到我们有通知名称,例如: “com.apple.system.loginWindows.logoutNoReturn”

    你可以注册到这些网站,这样就可以了。

    希望有一天这能帮助别人:)

        2
  •  2
  •   Irad K    6 年前

    当你说你已经将代码作为后台进程运行时,你的意思是它基于根据中的plist文件处理的启动守护进程吗 /Library/LaunchDeamon ? 在这种情况下,不会发送通知。试着在下面运行 Cocoa application

    我仍在寻找一种方法,在后台deamon过程中获取这些通知。

        3
  •  0
  •   H. Katsura    3 年前

    我能做到 NSWorkspaceWillPowerOffNotification applicationShouldTerminate: NSApplicationActivationPolicyAccessory 并将运行循环替换为 [NSApp run] . 如果您想继续监视所有注销(和/或关机尝试),它仍然不会很有用,因为它仅在用户已登录时启动进程时起作用,并且它只能检测当前UI登录会话的关机/注销通知和“应用程序应终止”委托。

    [NSApp运行]

    因此,如果你想继续监视用户的注销(或关机尝试),你需要一个非应用程序(没有 [NSApp运行] )过程。

    NSWorkspaceSessionDidBecomeActiveNotification NSWorkspaceSessionDidResignActiveNotification 工作无需 如果您想监视用户是关闭还是重新打开。

    或者,如果系统配置API适用于您的用例,您也可以尝试它。

    “技术问答QA1133:确定控制台用户登录状态” https://developer.apple.com/library/archive/qa/qa1133/_index.html

    听起来像 com.apple.system.loginwindow.logoutNoReturn 无论你想做什么,这都是最好的选择。很高兴知道!

    // cc powreoff-notification.m -o poweroff-notification -framework AppKit
    #import <AppKit/AppKit.h>
    
    @interface ShutDownHandler : NSObject <NSApplicationDelegate>
    
    - (void)computerWillShutDownNotification:(NSNotification *)notification;
    
    @end
    
    int main(int argc, char* argv[]) {
        @autoreleasepool {
            NSLog(@"%s", __func__);
            NSNotificationCenter* notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
    
            ShutDownHandler* sdh = [ShutDownHandler new];
    
            [NSApplication sharedApplication].delegate = sdh;
    
            [notCenter addObserver:sdh
                          selector:@selector(computerWillShutDownNotification:)
                              name:NSWorkspaceWillPowerOffNotification
                            object:nil];
    
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                [[NSFileManager defaultManager] createFileAtPath:@"./output.txt" contents:nil attributes:nil];
            });
    
            // without NSApplicationActivationPolicyAccessory, the [NSApp run] process gets killed on
            // poweroff/logout instead of getting the power off notification or applicationShouldTerminate:.
            [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
    
            // without [NSApp run], you won't get the power off notification or applicationShouldTerminate:.
            //[[NSRunLoop currentRunLoop] run];
            [NSApp run];
    
            // this process needs to be launched while the user has already logged in. otherwise,
            // you won't get the power off notification or applicationShouldTerminate:.
        }
    
        return 0;
    }
    
    @implementation ShutDownHandler
    
    - (void)computerWillShutDownNotification:(NSNotification *)notification {
        NSLog(@"%s", __func__);
        NSFileHandle* file = [NSFileHandle fileHandleForUpdatingAtPath: @"./output.txt"];
        [file seekToEndOfFile];
    
        NSDateFormatter* fmt = [NSDateFormatter new];
        [fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss\n"];
        NSDate* current = [NSDate date];
    
        NSString* dateStr = [fmt stringFromDate:current];
        [dateStr writeToFile:@"./output.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
    
    - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
    {
        NSLog(@"%s", __func__);
        return NSTerminateCancel;
    }
    
    @end