Browsing StackOverflow, I came across a question asking how to programmatically shut down the computer in Delphi when targeting OS X. Mysteriously, the question has been met with four downvotes as I write this, leaving it ‘on hold as off-topic’ until the darstardly questioner stops thinking a programmer’s Q&A site is a proper place for programming questions or something.
Anyhow, with respect to the question, one easy way to do the deed is to use a Cocoa NSAppleScript object to run the following piece of AppleScript:
tell application "Finder" to shut down
As desired, ‘to shut down’ can be replaced with ‘to restart’, ‘to sleep’ or ‘to log out’.
Now in Delphi, NSAppleScript (or more exactly, a wrapper interface type for NSAppleScript) is declared in the Macapi.Foundation unit. Alas, but this is misdeclared, or at least was when I last looked (see here– if someone wants to confirm this is still the case in the latest and greatest, please do in the comments). As such, you need to fix the declaration before using it. On the other hand, fixing it is easy:
uses Macapi.ObjectiveC, Macapi.CocoaTypes, Macapi.Foundation; type NSAppleScript = interface(NSObject) ['{0AB1D902-25CE-4F0B-A3BE-C4ABEDEB88BC}'] function compileAndReturnError(errorInfo: Pointer): Boolean; cdecl; function executeAndReturnError(errorInfo: Pointer): Pointer; cdecl; function executeAppleEvent(event: NSAppleEventDescriptor; error: Pointer): Pointer; cdecl; function initWithContentsOfURL(url: NSURL; error: Pointer): Pointer; cdecl; function initWithSource(source: NSString): Pointer; cdecl; function isCompiled: Boolean; cdecl; function source: NSString; cdecl; end; TNSAppleScript = class(TOCGenericImport<NSAppleScriptClass, NSAppleScript>) end; procedure TForm1.Button1Click(Sender: TObject); var Script: NSAppleScript; Error: Pointer; begin Error := nil; Script := TNSAppleScript.Wrap(TNSAppleScript.Alloc.initWithSource( NSSTR('tell application "Finder" to shut down'))); try if Script.executeAndReturnError(Error) = nil then raise EOSError.Create('AppleScript macro failed'); finally Script.release; end; end;
