执行某些系统事件,Mac OS X

4

我希望你能够通过我正在制作的应用程序关闭、重启、注销和休眠我的系统。我找不到任何本地的Objective C方法来完成这个任务,这真的很困难。

有人可以指导我如何最好地完成这个任务吗?

我已经尝试过:

  • 使用NSTask来运行shell脚本
  • 使用AppleScript
  • 使用IOPMAssertionDeclareUserActivity函数来使系统进入睡眠状态
NSString *scriptAction = @"restart"; // @"restart"/@"shut down"/@"sleep"/@"log out"
NSString *scriptSource = [NSString stringWithFormat:@"tell application \"Finder\" to %@", scriptAction];
NSAppleScript *appleScript = [[[NSAppleScript alloc] initWithSource:scriptSource] autorelease];
NSDictionary *errDict = nil;
if (![appleScript executeAndReturnError:&errDict]) {
    //
}

那一点也没有运气,还尝试了以下方法:
NSAppleScript* theScript = [[NSAppleScript alloc] initWithSource:
                            @"Tell application \"Finder\" to restart"];
if (theScript != NULL)
{
    NSDictionary* errDict = NULL;
    // execution of the following line ends with EXC
    if (YES == [theScript compileAndReturnError: &errDict])
    {
        [theScript executeAndReturnError: &errDict];
    }
    [theScript release];
}

运气不好


1
可能是Shutdown Mac Objective C的重复问题。 - jscs
2
技术问答1134应该会有所帮助:http://developer.apple.com/library/mac/#qa/qa1134/_index.html - jscs
嗨,Josh。实际上我发布了第一个问题。完全忘记了它。我已经尝试了所有列出的方法,包括问答法,但都没有成功。 - Sandeep Bansal
2个回答

11

我已经使用以下代码超过8年且没有出现问题:

MDRestartShutdownLogout.h:

#import <CoreServices/CoreServices.h>
/*
    *    kAERestart        will cause system to restart
    *    kAEShutDown       will cause system to shutdown
    *    kAEReallyLogout   will cause system to logout
    *    kAESleep          will cause system to sleep
 */
extern OSStatus MDSendAppleEventToSystemProcess(AEEventID eventToSend);

MDRestartShutdownLogout.m:

#import "MDRestartShutdownLogout.h"

OSStatus MDSendAppleEventToSystemProcess(AEEventID eventToSendID) {
    AEAddressDesc targetDesc;
    static const ProcessSerialNumber kPSNOfSystemProcess = {0, kSystemProcess };
    AppleEvent eventReply = {typeNull, NULL};
    AppleEvent eventToSend = {typeNull, NULL};

    OSStatus status = AECreateDesc(typeProcessSerialNumber,
         &kPSNOfSystemProcess, sizeof(kPSNOfSystemProcess), &targetDesc);

    if (status != noErr) return status;

    status = AECreateAppleEvent(kCoreEventClass, eventToSendID,
          &targetDesc, kAutoGenerateReturnID, kAnyTransactionID, &eventToSend);

    AEDisposeDesc(&targetDesc);

    if (status != noErr) return status;

    status = AESendMessage(&eventToSend, &eventReply,
                          kAENormalPriority, kAEDefaultTimeout);

    AEDisposeDesc(&eventToSend);
    if (status != noErr) return status;
    AEDisposeDesc(&eventReply);
    return status;
}

请注意,上述代码是基于来自Technical Q&A QA1134的代码,但我的代码重新使用了AESendMessage()而不是AESend()AESend()位于HIToolbox.framework中,该框架位于Carbon.framework中,因此无法用于64位应用程序。 (AESendMessage()包含在CoreServices中的AE.framework中)。


对我来说没用:(。使用此函数与任何操作将在调用AESendMessage时给出状态为-600的结果["procNotFound"]("no eligible process with specified descriptor")。有什么想法吗? - Alex
这个在没有沙盒的情况下运行得很完美。但是一旦开启沙盒,它就无法工作了。有人能告诉我需要启用哪些权限才能让它正常工作吗? - Jeba Moses

0

如果您是从GUI会话登录的,那肯定可以正常工作

如果您只是从ssh会话等没有GUI的会话登录,则无法正常工作。

请更详细地描述您的情况,包括您遇到的错误类型等。否则我们无法帮助您。


1
我完全没有收到任何错误信息。我已经在界面构建器中正确地连接了所有内容,分配了方法等等。但是当代码执行的时候,什么也没有发生。是的,这个应用程序将在基于GUI的应用程序上运行。 - Sandeep Bansal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接