AESendMessage

Mac OSX specific forum
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

AESendMessage

Post by Rinzwind »

Any PB example for AESendMessage available? As of now not :(

https://developer.apple.com/documentati ... endmessage
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: AESendMessage

Post by Mijikai »

wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: AESendMessage

Post by wilbert »

Rinzwind wrote:Any PB example for AESendMessage available? As of now not :(
Do you have any example code in Objective-C or Swift of what you want to do with the command ?
Windows (x64)
Raspberry Pi OS (Arm64)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: AESendMessage

Post by Rinzwind »

I do have a C-example

Code: Select all

#include <stdio.h> 
#include <CoreServices/CoreServices.h>
#include <Carbon/Carbon.h>

static OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend);

int main(void)
{
	const int bufferSize = 256;
	OSStatus error = noErr;
	char select [bufferSize];

	printf("1: Restart computer\n");
	printf("2: Shutdown computer\n");
	printf("3: Logout computer\n");
	printf("4: Sleep computer\n");
	printf("5: Quit All\n");
	printf("q: quit program\n");
	printf("please enter choice:\n");fflush(stdout);
	fgets(select, bufferSize, stdin);

	switch (select[0])
	{
		 case '1':
			//sending restart event to system
			error = SendAppleEventToSystemProcess(kAERestart);
			if (error == noErr)
				{printf("Computer is going to restart!\n");}
			else
				{printf("Computer wouldn't restart\n");}
		 break;
		
		 case '2':
			//sending shutdown event to system
			error = SendAppleEventToSystemProcess(kAEShutDown);
			if (error == noErr)
				{printf("Computer is going to shutdown!\n");}
			else
				{printf("Computer wouldn't shutdown\n");}
		 break;
		 case '3':
			//sending logout event to system
			error = SendAppleEventToSystemProcess(kAEReallyLogOut);
			if (error == noErr)
				{printf("Computer is going to logout!\n");}
			else
				{printf("Computer wouldn't logout");}
		 break;
		 case '4':
			//sending sleep event to system
			error = SendAppleEventToSystemProcess(kAESleep);
			if (error == noErr)
				{printf("Computer is going to sleep!\n");}
			else
				{printf("Computer wouldn't sleep");}
		break;				
	};

	return(0);
}

OSStatus SendAppleEventToSystemProcess(AEEventID EventToSend)
{
	AEAddressDesc targetDesc;
	static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess };
	AppleEvent eventReply = {typeNull, NULL};
	AppleEvent appleEventToSend = {typeNull, NULL};

	OSStatus error = noErr;

	error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, 
											sizeof(kPSNOfSystemProcess), &targetDesc);
	if (error != noErr)
	{
		return(error);
	}
	

	error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc, 
				   kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend);

	AEDisposeDesc(&targetDesc);
	if (error != noErr)
	{
		return(error);
	}

	//error = AESend(&appleEventToSend, &eventReply, kAENoReply, 
	//			  kAENormalPriority, kAEDefaultTimeout, NULL, NULL);


	error = AESendMessage(&appleEventToSend, &eventReply,
				                          kAENormalPriority, 0);//kAEDefaultTimeout);
	AEDisposeDesc(&appleEventToSend);
	if (error != noErr)
	{
		return(error);
	}

	AEDisposeDesc(&eventReply);

	return(error); 
}

Even the 'abcd' AEEvents is driving me crazy in PB. How to easily handle those..
The example code runs fine btw.

For what it's worth, here some definitions I played with:

Code: Select all

ImportC ""
  AECreateDesc(typeCode, *dataPtr, dataSize,  *result)
  AECreateAppleEvent(theAEEventClass, theAEEventID,  *target, returnID, transactionID, *result)
  AESendMessage(*event, *reply, sendMode, timeOutInTicks.l)
  AEDisposeDesc(theAEDesc)
EndImport

Structure ProcessSerialNumber
  HighLongOfPSN.l
  LowLongOfPSN.l
EndStructure

Structure AEDesc
  descriptorType.a[4]
  dataHandle.l
EndStructure

#typeNull = 'null'
#typeProcessSerialNumber = 'psn '
#kCoreEventClass = 'aevt'
#kAutoGenerateReturnID         = -1
#kAnyTransactionID             = 0 
#kAENormalPriority             = $00000000
#kAEDefaultTimeout             = -1
#kAEShutDown                   = 'shut'
#kAESleep                      = 'slep'
#noErr = 0
How to easily set descriptorType to one of the predefined constants? Guess PB doesn't like that (overflow compiler error).
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: AESendMessage

Post by wilbert »

Rinzwind wrote:Even the 'abcd' AEEvents is driving me crazy in PB. How to easily handle those..
The example code runs fine btw.
I'm doing something wrong but I don't know what.
I thought it had to be something like the code below but it keeps crashing. :?

Edit:
See post below for the updated working code
viewtopic.php?p=541150#p541150

Code: Select all

#noErr                    = 0
#kAnyTransactionID        = 0
#kAENormalPriority        = 0
#kAENoReply               = 1
#kSystemProcess           = 1
#kAEDefaultTimeout        = -1
#kAutoGenerateReturnID    = -1
#kAERestart               = $72657374; 'rest'
#kAEShutDown              = $73687574; 'shut'
#kAEReallyLogOut          = $726C676F; 'rlgo'
#kAESleep                 = $736C6570; 'slep'
#typeNull                 = $6E756C6C; 'null'
#typeProcessSerialNumber  = $70736E20; 'psn '
#kCoreEventClass          = $61657674; 'aevt'

ImportC ""
  AECreateDesc(typeCode, *dataPtr, dataSize, *result)
  AECreateAppleEvent(theAEEventClass, theAEEventID, *target, returnID, transactionID, *result)
  AEDisposeDesc(*theAEDesc)
  AESend(*event, *reply, sendMode, sendPriority, timeOutInTicks, *idleProc, *filterProc)
  AESendMessage(*event, *reply, sendMode, timeOutInTicks)
EndImport

Structure ProcessSerialNumber
  HighLongOfPSN.l
  LowLongOfPSN.l
EndStructure

Structure AEDesc
  desctiptorType.l
  dataHandle.l
EndStructure

Procedure.l SendAppleEventToSystemProcess(EventToSend.l)
  Protected.ProcessSerialNumber kPSNOfSystemProcess
  Protected.AEDesc targetDesc, eventReply, appleEventToSend
  Protected.l error
  
  kPSNOfSystemProcess\LowLongOfPSN = #kSystemProcess
  eventReply\desctiptorType = #typeNull
  appleEventToSend\desctiptorType = #typeNull
  
  error = AECreateDesc(#typeProcessSerialNumber, @kPSNOfSystemProcess, SizeOf(kPSNOfSystemProcess), @targetDesc)
  If error
    ProcedureReturn error
  EndIf
  
  error = AECreateAppleEvent(#kCoreEventClass, EventToSend, @targetDesc, #kAutoGenerateReturnID, #kAnyTransactionID, @appleEventToSend)
  AEDisposeDesc(@targetDesc)
  If error
    ProcedureReturn error
  EndIf
  
  error = AESendMessage(@appleEventToSend, @eventReply, #kAENormalPriority, 0)
  ;error = AESend(@appleEventToSend, @eventReply, #kAENoReply, #kAENormalPriority, #kAEDefaultTimeout, #Null, #Null)
  AEDisposeDesc(@appleEventToSend)
  If error
    ProcedureReturn error
  EndIf  
  
  AEDisposeDesc(@eventReply)
  
  ProcedureReturn error
  
EndProcedure



SendAppleEventToSystemProcess(#kAESleep)
Last edited by wilbert on Wed Aug 28, 2019 3:44 pm, edited 1 time in total.
Windows (x64)
Raspberry Pi OS (Arm64)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: AESendMessage

Post by Rinzwind »

Thanks so far..
Huh?! moment:
After the line...
error = AECreateDesc(#typeProcessSerialNumber, @kPSNOfSystemProcess, SizeOf(kPSNOfSystemProcess), @targetDesc)
...the field eventReply\desctiptorType is changed from 1853189228 to 1? :?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: AESendMessage

Post by wilbert »

Rinzwind wrote:Huh?! moment:
That's great. You found the problem. It is working now. :D

Code: Select all

#noErr                    = 0
#kAnyTransactionID        = 0
#kAENormalPriority        = 0
#kAENoReply               = 1
#kSystemProcess           = 1
#kAEDefaultTimeout        = -1
#kAutoGenerateReturnID    = -1
#kAERestart               = $72657374; 'rest'
#kAEShutDown              = $73687574; 'shut'
#kAEReallyLogOut          = $726C676F; 'rlgo'
#kAESleep                 = $736C6570; 'slep'
#typeNull                 = $6E756C6C; 'null'
#typeProcessSerialNumber  = $70736E20; 'psn '
#kCoreEventClass          = $61657674; 'aevt'

ImportC ""
  AECreateDesc(typeCode, *dataPtr, dataSize, *result)
  AECreateAppleEvent(theAEEventClass, theAEEventID, *target, returnID, transactionID, *result)
  AEDisposeDesc(*theAEDesc)
  AESend(*event, *reply, sendMode, sendPriority, timeOutInTicks, *idleProc, *filterProc)
  AESendMessage(*event, *reply, sendMode, timeOutInTicks)
EndImport

Structure ProcessSerialNumber
  HighLongOfPSN.l
  LowLongOfPSN.l
EndStructure

Structure AEDesc
  desctiptorType.l
  *dataHandle
EndStructure

Procedure.l SendAppleEventToSystemProcess(EventToSend.l)
  Protected.ProcessSerialNumber kPSNOfSystemProcess
  Protected.AEDesc targetDesc, eventReply, appleEventToSend
  Protected.l error
  
  kPSNOfSystemProcess\LowLongOfPSN = #kSystemProcess
  eventReply\desctiptorType = #typeNull
  appleEventToSend\desctiptorType = #typeNull
  
  error = AECreateDesc(#typeProcessSerialNumber, @kPSNOfSystemProcess, SizeOf(kPSNOfSystemProcess), @targetDesc)
  If error
    ProcedureReturn error
  EndIf
  
  error = AECreateAppleEvent(#kCoreEventClass, EventToSend, @targetDesc, #kAutoGenerateReturnID, #kAnyTransactionID, @appleEventToSend)
  AEDisposeDesc(@targetDesc)
  If error
    ProcedureReturn error
  EndIf
  
  error = AESendMessage(@appleEventToSend, @eventReply, #kAENormalPriority, 0)
  ;error = AESend(@appleEventToSend, @eventReply, #kAENoReply, #kAENormalPriority, #kAEDefaultTimeout, #Null, #Null)
  AEDisposeDesc(@appleEventToSend)
  If error
    ProcedureReturn error
  EndIf  
  
  AEDisposeDesc(@eventReply)
  
  ProcedureReturn error
  
EndProcedure



SendAppleEventToSystemProcess(#kAESleep)
Windows (x64)
Raspberry Pi OS (Arm64)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: AESendMessage

Post by Rinzwind »

Great it works. Heel erg bedankt voor de hulp.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: AESendMessage

Post by wilbert »

Alternative code (macOS 10.11+) ...

Code: Select all

#typeProcessSerialNumber  = $70736E20; 'psn '
#kCoreEventClass          = $61657674; 'aevt'
#kAERestart               = $72657374; 'rest'
#kAEShutDown              = $73687574; 'shut'
#kAEReallyLogOut          = $726C676F; 'rlgo'
#kAESleep                 = $736C6570; 'slep'

#kAEDefaultTimeout        = -1
#kAENormalPriority        =  0
#kAnyTransactionID        =  0
#kAutoGenerateReturnID    = -1
#NSAppleEventSendNoReply  =  1


Procedure.l SendAppleEventToSystemProcess(EventToSend.l)
  
  Static kPSNOfSystemProcess.q = $100000000
  
  Protected.i target, event, error
  
  target = CocoaMessage(0, 0, "NSAppleEventDescriptor descriptorWithDescriptorType:", #typeProcessSerialNumber, 
                        "bytes:", @kPSNOfSystemProcess, "length:", 8)
  
  event = CocoaMessage(0, 0, "NSAppleEventDescriptor appleEventWithEventClass:", #kCoreEventClass, 
                       "eventID:", EventToSend, "targetDescriptor:", target, 
                       "returnID:", #kAutoGenerateReturnID, "transactionID:", #kAnyTransactionID)
  
  CocoaMessage(0, event, "sendEventWithOptions:", #NSAppleEventSendNoReply, 
               "timeout:", #kAEDefaultTimeout, "error:@", @error)
  
  ProcedureReturn Bool(error = #nil)
  
EndProcedure



SendAppleEventToSystemProcess(#kAESleep)
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply