-
-
Save erikng/134a4574e2bd993f8569bf281ea4a7cc to your computer and use it in GitHub Desktop.
Send polite Logout / "really" Logout / Restart / Shutdown Apple Events to loginwindow via python and pyObjC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct, objc | |
from Foundation import NSBundle | |
from Cocoa import NSAppleEventDescriptor | |
def OSType(s): | |
# Convert 4 character code into 4 byte integer | |
return struct.unpack('>I', s)[0] | |
# Create an opaque pointer type to mask the raw AEDesc pointers we'll throw around | |
AEDescRef = objc.createOpaquePointerType('AEDescRef', '^{AEDesc=I^^{OpaqueAEDataStorageType}}') | |
# Load AESendMessage from AE.framework for sending the AppleEvent | |
AE_bundle = NSBundle.bundleWithIdentifier_('com.apple.AE') | |
functions = [("AESendMessage", b"i^{AEDesc=I^^{OpaqueAEDataStorageType}}^{AEDesc=I^^{OpaqueAEDataStorageType}}iq"),] | |
objc.loadBundleFunctions(AE_bundle, globals(), functions) | |
# defined in AEDataModel.h | |
kAENoReply = 1 | |
kAENeverInteract = 16 | |
kAEDefaultTimeout = -1 | |
kAnyTransactionID = 0 | |
kAutoGenerateReturnID = -1 | |
# defined in AEDataModel.h | |
typeAppleEvent = OSType('aevt') | |
typeApplicationBundleID = OSType('bund') | |
# defined in AERegistry.h | |
kAELogOut = OSType('logo') | |
kAEReallyLogOut = OSType('rlgo') | |
kAEShowRestartDialog = OSType('rrst') | |
kAEShowShutdownDialog = OSType('rsdn') | |
# Build a standalone application descriptor by bundle id | |
loginwindowDesc = NSAppleEventDescriptor.alloc().initWithDescriptorType_data_(typeApplicationBundleID, buffer('com.apple.loginwindow')) | |
# build an event descriptor with our app descriptor as the target and the kAELogOut eventID | |
event = NSAppleEventDescriptor.appleEventWithEventClass_eventID_targetDescriptor_returnID_transactionID_( | |
typeAppleEvent, kAELogOut, loginwindowDesc, kAutoGenerateReturnID, kAnyTransactionID) | |
eventDesc = event.aeDesc() | |
# Send a polite logout (returns immediately) | |
err = AESendMessage(eventDesc, None, kAENoReply|kAENeverInteract, kAEDefaultTimeout) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment