"waking" computer to run script from mail rule

I say “waking” because it’s not really asleep, but the display is.

Anywho, I’ve an awesome budget workbook in Excel (functioning as my place to implement new VBA ideas with a degree of practical return on time spent), and the next enhancement was to be able to send myself an email when out and about and have mail run an applescript to open the workbook and place the new line item into it.

It works, and I overcame the problem not being able to get the display to come back on by using a tool called “SleepDisplay”. However, the script will only wake the display, enter the password, and execute if the screen’s been asleep for a short time, less than 30 minutes or so (though I’ve yet to exhaustively pinpoint exactly how long).

If its within this time frame, then everything works perfectly, but if not, then everything works except the script itself, meaning that Mail receives the message the other actions of the rule are executed, but the applescript fails to run.

Upon waking the display and logging back in manually, I can see that excel has been activated (icon appears on the dock), but it doesn’t do anything until I click it’s icon. After clicking excel’s icon, it immediately opens the budget workbook, inserts the line item, and does everything else it was supposed to do.

So what’s my problem? Is there some deeper level of sleeping the display without actually putting the computer to sleep? I know the computer is still awake because I can send it emails and it will beep at me and execute any other rules that are completely within Mail (ie no applescript), including auto-responding with a message. Given the hanging excel instance when I log back into the computer, is the problem to due with calling excel? The display never comes on when the ~30 minutes have been passed, so is there something wrong with the SleepDisplay tool?

Any help is appreciated.

Thanks,

Tim

The full script follows, including subroutines, so if you’d like to test this, just change the pointer to the budget file. Directly below is a link to a blank copy of the glorious budget sheet itself:
Edit This workbook is macro-enabled, but it’s completely safe. Scan it before opening if you’d like to be (more) safe.

https://www.dropbox.com/s/17elck604t3nyvz/budget%20template.xlsm

Use the following formatting in the trigger email to conform with the script:

Budget item:
(day, ## for day of current month, leave blank if for same day;
w, “who” the line item is for, enter 1,2 or 3, points towards names specified in the budget workbook;
t, type, enter i or e, stands for income and expense;
d1, primary description/category, must match category specified in budget workbook;
d2, secondary description, any value or string;
$, number only for amount)
AVOID HYPHENS WHEN ENTERING INFO, AS HYPHENS ARE USED AS THE DELIMITER


day-
w-
t-
d1-
d2-
$-


EXAMPLE:


day-15
w-1
t-e
d1-shopping
d2-test
$-100



some notes on the budget workbook:

  • used for two people sharing a single account or monetary supply
  • data validation used so only income/expense categories specified in the “year” sheet can be entered
  • conditional formatting color codes each line item based on income/expense of person 1, person 2, or a shared income/expense
  • dynamic charts on “year” sheet get data from the hidden “charts” sheet
  • VBA userforms for entering in all line items, common income/expenses, and sorting line items based on several criteria

Finally, here’s the script itself. I’ve only commented it until the end of the part that wakes the display and logs in.

(*
	Tim Wilson
	3/19/2013
	Script to add line items to budget worksheet from incoming message in Mail
*)

-- first two lines are blocks to react to the rule in Mail
using terms from application "Mail"
	
	on perform mail action with messages theSelectedMessages
		
		-- checks if system sounds are muted and mutes them if not, unmuting when finished
		set isMuted to output muted of (get volume settings)
		set changeMute to false
		if isMuted is false then
			set changeMute to true
			set volume with output muted
		end if
		
		-- check to see if display is asleep, wakes display if asleep and resleeps it when finished
		set isSleeping to false
		set sleeping to 1
		set awake to 4
		-- shell script that returns sleep status of display
		set display_sleep_state to parseLine(do shell script "ioreg -n IODisplayWrangler |grep -i IOPowerManagement", "CurrentPowerState")
		if item 2 of display_sleep_state contains sleeping then
			set isSleeping to true
			set passKey to "my_super_secret_password" -- not really my password
			
			-- shell script calling the "SleepDisplay" tool
			do shell script "/usr/local/bin/SleepDisplay --wake"
			
			tell application "System Events"
				delay 5
				-- entering my password into the login window
				repeat with i from 1 to count of passKey
					keystroke item i of passKey
					delay 0.01
				end repeat
				key code 36 --return key
				delay 1
			end tell
			
			
		else if item 2 of display_sleep_state contains awake then -- unused, but I keep it here anyways :)
		end if
		delay 0.5
		
		set dateTime to current date
		set currentMonth to month of dateTime as number
		set currentYear to year of dateTime as number
		set currentDay to day of dateTime as number
		
		set budgetFile to "HDD:Users:Haiiro:Dropbox:" & currentYear & " Budget.xlsm" as alias
		
		if currentMonth is 1 then
			set sheetName to "Jan"
			set numOfDays to 31
		else if currentMonth is 2 then
			set sheetName to "Feb"
			if currentYear mod 4 = 0 then
				set numOfDays to 29
			else
				set numOfDays to 28
			end if
		else if currentMonth is 3 then
			set sheetName to "Mar"
			set numOfDays to 31
		else if currentMonth is 4 then
			set sheetName to "Apr"
			set numOfDays to 30
		else if currentMonth is 5 then
			set sheetName to "May"
			set numOfDays to 31
		else if currentMonth is 6 then
			set sheetName to "Jun"
			set numOfDays to 30
		else if currentMonth is 7 then
			set sheetName to "Jul"
			set numOfDays to 31
		else if currentMonth is 8 then
			set sheetName to "Aug"
			set numOfDays to 31
		else if currentMonth is 9 then
			set sheetName to "Sep"
			set numOfDays to 30
		else if currentMonth is 10 then
			set sheetName to "Oct"
			set numOfDays to 31
		else if currentMonth is 11 then
			set sheetName to "Nov"
			set numOfDays to 30
		else if currentMonth is 12 then
			set sheetName to "Dec"
			set numOfDays to 31
		end if
		
		repeat with currentMessage in theSelectedMessages
			
			set fileText to content of currentMessage
			
			set itemList to {}
			set i to 0
			set fullItem to 5
			
			set tempItem to {itemDay:"", itemWho:"", itemType:"", itemDesc:"", itemDesc2:"", itemAmount:""}
			
			set err to false
			
			repeat with currentLine in paragraphs of fileText
				set lineInfo to parseLine(currentLine, "-")
				if (count of lineInfo) is not less than 2 then
					if item 1 of lineInfo contains "Day" then
						set itemDay of tempItem to item 2 of lineInfo
						set i to i + 1
						set fullItem to 6
					else if item 1 of lineInfo contains "w" then
						set itemWho of tempItem to item 2 of lineInfo as number
						set i to i + 1
					else if item 1 of lineInfo contains "t" then
						set itemType of tempItem to item 2 of lineInfo
						set i to i + 1
					else if item 1 of lineInfo contains "d1" then
						set itemDesc of tempItem to titleCase(item 2 of lineInfo)
						set i to i + 1
					else if item 1 of lineInfo contains "d2" then
						set itemDesc2 of tempItem to titleCase(item 2 of lineInfo)
						set i to i + 1
					else if item 1 of lineInfo contains "$" then
						set itemAmount of tempItem to item 2 of lineInfo
						set i to i + 1
					end if
				end if
				if i ≥ fullItem then
					if itemType of tempItem is "i" then
						set itemType of tempItem to "Income"
					else if itemType of tempItem is "e" then
						set itemType of tempItem to "Expense"
					end if
					if itemDay of tempItem is not "" and itemDay of tempItem is greater than numOfDays then
						set errorMsg to "The specified day of an item is incorrect. Must be no greater than " & numOfDays & ".

No items were added."
						set err to true
						exit repeat
					end if
					if itemDay of tempItem is not "" then
						set itemDay of tempItem to (currentMonth & "/" & itemDay of tempItem & "/" & currentYear) as string
					end if
					set end of itemList to tempItem
					set tempItem to {itemDay:"", itemWho:"", itemType:"", itemDesc:"", itemDesc2:"", itemAmount:""}
					set i to 0
					set fullItem to 5
				end if
			end repeat
			
			
			if err is false then
				set returnValue to insertItems(budgetFile, sheetName, itemList)
				if item 1 of returnValue is 1 then
					set errorMsg to "The current month is full, so no more items can be entered. Only the first " & item 2 of returnValue & " item(s) were added."
					set err to true
				else if item 1 of returnValue is 2 then
					set errorMsg to "The description of item " & (item 2 of returnValue) + 1 & " didn't match with set descriptions.

The first " & item 2 of returnValue & " item(s) were added.

Expenses:
"
					repeat with desc in (item 3 of returnValue)
						set errorMsg to errorMsg & "      " & desc & "
"
					end repeat
					set errorMsg to errorMsg & "
Income:
"
					repeat with desc in (item 4 of returnValue)
						set errorMsg to errorMsg & "      " & desc & "
"
					end repeat
					set err to true
				else if item 1 of returnValue is 3 then
					set errorMsg to "The person of item " & (item 2 of returnValue) + 1 & " is incorrect. Must be 1, 2, or 3.

The first " & item 2 of returnValue & " item(s) were added."
					set err to true
				end if
			end if
			
			if err is true then
				errorMessage(errorMsg, fileText)
			else
				successMessage(item 2 of returnValue, fileText)
			end if
			
			delete currentMessage
			
		end repeat
		
		if isSleeping is true then do shell script "/usr/local/bin/SleepDisplay"
		
		delay 4
		if changeMute is true then set volume without output muted
		
	end perform mail action with messages
	
end using terms from

on errorMessage(errorMsg, fileText)
	
	set errorMsg to errorMsg & "

Original data: 

" & fileText
	
	if my appisrunning("Mail") then
		set dontQuit to true
	else
		set dontQuit to false
	end if
	
	tell application "Mail"
		set theMessage to make new outgoing message with properties {visible:true, subject:"Budget - Add Item Error", content:errorMsg}
		tell theMessage
			make new recipient at end of to recipients with properties {name:"Tim Wilson", address:"twilsonco@gmail.com"}
		end tell
		set sent to send theMessage
		if dontQuit is false then
			if sent is true then quit
		end if
	end tell
	
end errorMessage

on successMessage(itemList, fileText)
	
	if my appisrunning("Mail") then
		set dontQuit to true
	else
		set dontQuit to false
	end if
	
	set dateTime to current date
	set currentMonth to month of dateTime as number
	set currentYear to year of dateTime as number
	set currentDay to day of dateTime as number
	
	set messageText to "The following item(s) have been added to the budget workbook:

"
	set i to 1
	repeat with currentItem in itemList
		if itemDay of currentItem is "" then
			set itemDate to (currentMonth & "/" & currentDay & "/" & currentYear) as string
		else
			set itemDate to itemDay of currentItem
		end if
		set messageText to messageText & "Date: " & itemDate & "
Person: " & itemWho of currentItem & "
Type: " & itemType of currentItem & "
Description: " & itemDesc of currentItem & "
Secondary Description: " & itemDesc2 of currentItem & "
Amount: $" & itemAmount of currentItem & "

"
	end repeat
	
	set messageText to messageText & "

Original data: 

" & fileText
	
	tell application "Mail"
		set theMessage to make new outgoing message with properties {visible:true, subject:"Budget - Add Item Success", content:messageText}
		tell theMessage
			make new recipient at end of to recipients with properties {name:"Tim Wilson", address:"twilsonco@gmail.com"}
		end tell
		set sent to send theMessage
		if dontQuit is false then
			if sent is true then quit
		end if
	end tell
	
end successMessage

on insertItems(excelFile, sheetName, itemList)
	
	set itemNum to count of itemList
	set insertNum to 0
	set descMatch to false
	set userNumbers to {1, 2, 3}
	
	tell application "Microsoft Excel"
		
		open excelFile
		repeat with currentItem in itemList
			tell worksheet "Year"
				if itemWho of currentItem is not in userNumbers then
					quit saving no
					return {3, insertNum}
				end if
				set itemWho of currentItem to value of cell ("O" & (itemWho of currentItem) + 32)
				if itemType of currentItem is "Expense" then
					repeat with i from 32 to 44
						if itemDesc of currentItem contains value of cell ("B" & i) then
							set descMatch to true
							exit repeat
						end if
					end repeat
				else if itemType of currentItem is "Income" then
					repeat with i from 32 to 39
						if itemDesc of currentItem contains value of cell ("G" & i) then
							set descMatch to true
							exit repeat
						end if
					end repeat
				end if
			end tell
			if descMatch is false then
				set expList to {}
				set inList to {}
				tell worksheet "Year"
					repeat with i from 32 to 44
						if value of cell ("B" & i) is not "" then set end of expList to value of cell ("B" & i)
					end repeat
					repeat with i from 32 to 39
						if value of cell ("G" & i) is not "" then set end of inList to value of cell ("G" & i)
					end repeat
				end tell
				quit saving no
				return {2, insertNum, expList, inList}
			end if
			tell worksheet sheetName
				repeat with i from 5 to 104
					if value of cell ("D" & i) is "" then
						if itemDay of currentItem is not "" then set value of cell ("C" & i) to itemDay of currentItem
						set value of cell ("D" & i) to itemWho of currentItem
						set value of cell ("E" & i) to itemType of currentItem
						set value of cell ("F" & i) to itemDesc of currentItem
						set value of cell ("G" & i) to itemDesc2 of currentItem
						set value of cell ("H" & i) to itemAmount of currentItem
						set insertNum to insertNum + 1
						exit repeat
					end if
				end repeat
			end tell
		end repeat
		
		if i = 104 and insertNum < itemNum then
			quit saving no
			return {1, insertNum}
		else
			run VB macro "dateSort"
			tell active workbook
				save workbook as filename (excelFile as text) file format macro enabled XML file format with overwrite
			end tell
			quit
		end if
		
	end tell
	return {0, itemList}
	
end insertItems

on parseLine(theLine, delimiter)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {delimiter}
	set theTextItems to theLine's text items
	set AppleScript's text item delimiters to astid
	
	repeat with i from 1 to (count theTextItems)
		if (item i of theTextItems is "") then set item i of theTextItems to missing value
	end repeat
	
	return theTextItems's every text
end parseLine

on titleCase(_string)
	set _code to "import sys; print sys.argv[1].title()"
	set _script to "/usr/bin/python -c " & _code's quoted form & " " & _string's quoted form
	return do shell script _script
end titleCase

on appisrunning(appName)
	tell application "System Events" to (name of processes) contains appName
	-- returns true if excel is running
end appisrunning

Model: MBP-r
AppleScript: 2.2.4
Browser: Safari 536.25
Operating System: Mac OS X (10.8)

Hi,

no solution to your problem, but this is a shorter way to determine sheetName and numOfDays


set dateTime to current date
set budgetFile to ((path to home folder as text) & "Dropbox:" & year of currentYear & " Budget.xlsm") as alias
set numOfDays to 32 - ((dateTime + (32 - (dateTime's day)) * days)'s day) -- number of days of current month
set sheetName to text 1 thru 3 of (month of dateTime as text) -- abbreviated month name

Cool! Thanks! I’ve meager programming experience at best, but applescript always has a way that’s 50 times more elegant than mine. And you’re usually one of the guys who shows me!

Thanks again.

Ever played around with this screen waking business? From what I read, with pre-lion you could just send system events a keystroke and that would do the trick, but now only hardware keypresses seem to work. I have no idea how the SleepDisplay thing works, but other programs can wake the screen too (and even after a considerable time), so I know there’s a solution.

Hi scriptim,

Here’s part of a little script that I used to check the screensaver app. This script is made to run in the Applescript Editor:


-- wait for screen saver
set proc_list to {}
repeat until "ScreenSaverEngine" is in proc_list
	tell application "System Events"
		set proc_list to name of every process
	end tell
	delay 2
end repeat
say "screen saver on"

-- wait two minutes (one minute until display sleep + one minute)
set target_date to (current date) + 2 * minutes
repeat until (current date) > target_date
	delay 2
end repeat

-- keystroke space turns off screensaver, but not display sleep
tell application "System Events"
	tell process "Finder"
		keystroke space
	end tell
end tell
say "screensaver off"

For the test, I have the screensaver set to run after one minute and the display sleep to go off after two minutes of idle time. In the script, the target_date is set for about three minutes of idle time. Then, System Events turns off the screen saver, but the display sleep does not wake. So, you’re right that you cannot keystroke to wake from display sleep. But, you notice the the script still runs in display sleep as the program says “screensaver off”.

Just testing stuff. You can wake up the computer from any sleep (laptop lid up) with unix pmset I think it was. Getting late so I had to rush.

Editted: I made a mistake at the end there when it says screensaver off. I don’t really know if the screen saver is off. Had to get a list of process names first. But anyway, you know the script is still running after three minutes of idle time.

gl,

Model: MBP
AppleScript: 2.2.3
Browser: Safari 536.26.17
Operating System: Mac OS X (10.8)

Thanks gl,

It might be a pseudo-solution to resort to using the screensaver rather than sleeping the display, although I’m not particularly fond of that idea.

I forgot to include information on the SleepDisplay tool. Here’s the url for the full distribution:

and here’s a script to install it in the usr/local/bin folder:

--go to the folder "..../bigkm-SleepDisplay-...../dist/1.0/x64/"
choose file with prompt "Select the executable 'SleepDisplay'" 
set tFile to quoted form of POSIX path of the result
do shell script "/bin/mkdir -p /usr/local/bin/ && /bin/mv -f " & tFile & " /usr/local/bin/SleepDisplay" with administrator privileges

Hi scriptim,

I like to sleep the computer completely also. Lest wear and tear on the hardwear. :slight_smile:

Anyway, I quickly corrected modified the script:


-- wait for screen saver
set proc_list to {}
repeat until "ScreenSaverEngine" is in proc_list
	tell application "System Events"
		set proc_list to name of every process
	end tell
	delay 2
end repeat
say "screen saver on"

-- wait two minutes (one minute until display sleep + one minute)
set target_date to (current date) + 2 * minutes
repeat until (current date) > target_date
	delay 2
end repeat

-- keystroke space does not turn off anything
tell application "System Events"
	tell process "Finder"
		keystroke space
	end tell
	set process_list to name of every process
end tell
if "ScreenSaverEngine" is in process_list then
	say "screensaver on"
else
	say "screensaver off"
end if
say "I'm done."

and found that the screensaver was still on also. The keystrokes seems to not have turned it off. Still needs some testing because I might to add some delays to make sure. I already tried "key down’ but haven’t tried key codes.

I’m working on a program that will wake the computer on notifications, so it’s not out of the realm of what what you want to do. Or, maybe it’s something with the Mail app in your situation. I can’t think that the Mail app won’t run the script when in display sleep. It might have some thing to do with Mail.

Editted:
Btw, there’s a lot of examples on this site with pmset and waking your computer at certain times although not dynamically.

gl,

Hello.

ctrl-shift eject puts displays to sleep

opt-cmd eject puts Mac to sleep

I have a script to toggle the need for a password to wake stuff up gain screen/mac.

script disablePasswordPrompt
	tell application "System Preferences"
		tell anchor "General" of pane "com.apple.preference.security" to reveal
		activate
	end tell
	tell application id "sevs"
		set UI elements enabled to true
		set a to value of checkbox 2 of tab group of window 1 of application process "System Preferences" as integer
		if a = 1 then
			tell checkbox 2 of tab group of window 1 of application process "System Preferences" to click
		end if
	end tell
	delay 0
	tell application "System Preferences" to quit
end script
tell disablePasswordPrompt to run
script EnablePasswordPrompt
	tell application "System Preferences"
		tell anchor "General" of pane "com.apple.preference.security" to reveal
		activate
	end tell
	tell application id "sevs"
		set UI elements enabled to true
		set a to value of checkbox 2 of tab group of window 1 of application process "System Preferences" as integer
		if a = 0 then
			tell checkbox 2 of tab group of window 1 of application process "System Preferences" to click
		end if
	end tell
	delay 0
	tell application "System Preferences" to quit
end script
tell EnablePasswordPrompt to run

I realize this is far from what you are dealing with I looked at it, and it turns out that you can use the force argument of pmset, to make new settings take effect immediately, like: (needs chmod u+x or chmod gu+x )

#!/bin/bash
pmset displaysleep 0 force

Then I tried: sleep 10 && ./theCommand, and the screen woke up. so it is as simple as that really. to force it awake. But now you’ll have to set the display interval again. :expressionless:

@ gl

All mail rules run completely when display is asleep for any amount of time, so long as they aren’t this script, so I don’t think it’s a problem with Mail running rules.

I haven’t tested other, less involved, scripts to see if they’ll run when the display is asleep when triggered by a mail rule.

Also, in the situation where my script doesn’t wake the screen; upon waking the screen manually, excel is already running, but not doing anything. When I click its (excel’s) icon in the dock then it opens the budget file and continues where it apparently left off. Point being that the script get’s past the point where the screen should have been woken up and starts the excel stuff.

My main concern here is: why should the SleepDisplay tool work for time < minutes but stop working after longer periods, even though only the display is asleep in all cases?

@ McUsr

When did you become McUsr 2?

Also, after waking the screen (successfully), my script enters my password to login to the user. Wouldn’t disabling the login box not work if the user was already suspended?

When I successfully made a login script for this site, and lost my password in the process. :smiley:

You have to disable the password while logged in as the user, i.e up front.

Hi,

I’m trying to learn about this also. What I was thinking, is that if you can turn off the screen saver, then the computer will wake up for anything. I did this with pmset I think. I’ll look through the scripts to find that. One thing about pmset is that you need to know exactly what time you want the computer to wake up before hand.

Playing golf today so won’t be back until tomorrow maybe.:slight_smile:

I just remembered something I was thinking about. Maybe your script is timing out! Just a long shot.

gl,

Hello.

The pmset command I posted, didn’t work, it must have been the movement sensor that kicked in, this however does work for waking up the display: ( On SL at least).

You’ll need click click, and figure out a safe place to click. (you’ll have to find cliclick on the net)

sleep 5 ; cliclick c 75 75

works!

Edit
But I like SleepDisplay that scriptim provided much better! :slight_smile: . No fuzz, it does what it should.

Golf . It is more practical with ice hockey or skiing here… On the other hand, I have a great program for computing the traction of a golf-ball! :slight_smile:

I really can’t understand why the SleepDisplay should stop to work after 30 minutes, it really must be something else I think. But try looking into your console log after something happens, and look for the string IODisplayWrangler, then look before it, if there are some other errors. One possibility is that there is a depency of this service for something else, that is stale while your computer has been idle for 30 minutes.

Sorry McUsrII,

I didn’t see your pmset in your script until now.:smiley:

gl,

@ gl

The script doesn’t run until the email arrives, and the waking up part is the first thing it does, so timing out isn’t a possibility.

@ McUsrII

If only I was still on 10.6. Starting with 10.7, simulated mouse clicks and key presses aren’t allowed to wake the screen.

Again, this SleepDisplay thing works fine if the display has only been asleep for a short time, but after that amount of time it stops working.

Other apps (the LogMeIn app, for example) can wake the screen after any amount of time, and still works fine in 10.7/10.8, so I know this is doable. Might be a revision of SleepDisplay that crushes my woes.

Yes. maybe a revision of SleepDisplay will crush your woes.

But then you’ll have to file an issue, explaining the problem.

And before that, you’ll have to be absolutely sure that it is SleepDisplay, and not mail, that errs.

I presume you can make mail make your computer beep after 30 minutes.

What I think is happening, is when SleepDisplay is trying to register with IOKIt, then IOKit is on its way to hibernating or something, so it returns NULL, before the operation is executed. So no “service” is registrated, and nothing is executed, it just fails silently. But maybe there is something in a logfile. ConsoleLog, when the service fails to register.

This is of course just guessings, but as I said, try filing an issue at gitHub.

Edit

This is indeed very strange, because if mail processes your rule, after 30 minutes, then your system is up and going.
So it has really nothing to do with “preparing hibernation” I don’t think the IOKIt is particularily single-threaded either, so I have a hard time believing that some other failed process can make it hang. But.There may be some other process in progress that blocks it, no matter what I believe.

Here is a tinkered version of the code, so now you can at least see that SleepDisplay executed like it should, but you’ll have to test for ~/SleepDisplay.txt before you run SleepDisplay in your mail rule, and remove it if it exist.
If the file doesn’t exist after you have run SleepDisplay in your mail rule, then you know it didn’t work.
I post the code in public, so there is no doubt as to what changes I have made to it. :slight_smile:

#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
#include <stdlib.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSArray *params = [[NSProcessInfo processInfo] arguments];
    BOOL shouldWake = NO;

    for (NSString *arg in params)
    {
        if([arg isEqualToString:@"-wake"] || [arg isEqualToString:@"--wake"] || [arg isEqualToString:@"-w"])
        {
            shouldWake = YES;
        }
        
        if([arg isEqualToString:@"-help"] || [arg isEqualToString:@"--help"] || [arg isEqualToString:@"-h"])
        {
            printf("usage: SleepDisplay [-w]\n");
            printf("Without options, sleeps the display (not system sleep)\n");
            printf("use with the -w (--wake) option to wake\n");
            // quit.
            [pool drain];
            return 0;
        }
    }
    
    io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler");
    if(entry)
    {
        IORegistryEntrySetCFProperty(entry, CFSTR("IORequestIdle"), shouldWake ? kCFBooleanFalse : kCFBooleanTrue);
        IOObjectRelease(entry);
	system( "echo \"Slept\" >~/SleepDisplay.txt") ;
    }
    
    [pool drain];
    return 0;
}

Make a copy of the project, and copy over the code in SleepDisplay.m with this, to create a “test-version”.

But first and foremost: Can you make “the computer Beep” after 30 minutes by the mail rule?

McUsrII, where did you get control shift eject from? I don’t think I ever saw that. Come to think of it it sounds familiar.

Honestly?

First time I got from Mac OsX Hints, this time I got it from lifehacker. Haven’t used it for a while, so I had to google it.

(You can also easily lock the screen under the “lock” icon on the menu.)

it’s the hotkeys put there only so apple employees can bedazzle poor customers that don’t know any better. This way they can smack a few keys and the customer’s computer restarts, then they do some random simultaneous 6-key hold during boot and get to some other ‘mysterious’ place, and the customer is like, “wow, a genius…”

ctrl-shift-eject sleeps screen
ctrl-command-eject restarts
ctrl-option-command-eject shuts down (good one for unsuspecting friends, or enemies)
option-command-eject sleeps computer
shift-ctrl-option-command-eject actually ejects you from your seat *additional hardware necessary

Thanks McUsr. I’ll verify that I can beeb the computer (i assume you mean by way of a mail triggered applescript, to verify that at least applescripts can run), and run the tester SleepDisplay to see if that part of my script is running.

:smiley:

Actually ctrl-F7 is my favorite, as it takes me to the filename field in the file save dialog.

ctrl power is also useful, because that lets you turn your mac off, when everything else hangs.

It is cool to have those keys, more cool than not. :slight_smile: Seriously, it makes you do stuff faster, that part is bigger than the gimmick.

If the SleepDisplay tester script generate the SleepDisplay.txt file in your home directory, after creating the mail rule, then something is wrong with the design of the code, if the file doesn’t get to be generated, then there are problems with registering the “service”.

Either one of them: file an issue with it at gitHub, I at least must admit that I have no idea as to why it won’t work, when the computer has been idle.

On last trick would however be to use the setuid trick: sudo chown root:wheel SleepDisplay, and then sudo chmod u+s SleepDisplay so it runs with root permissions from your mail rule. It may help. But then you should look for the SleepDisplay.txt file in your root directory (/SleepDisplay.txt). I hope you try without setting user id of the command to root first though. :slight_smile:

Hello.

I just say this to insure that thing will progress as expected: you’ll have to build the DisplaySleep command in XCode.

And. Since this is a complex problem, I really want you to create a log file. you use the handler below like this:

my logit("I am about to try SleepDisplay","heavymailrule")

then you can look for your heavymailrule log at ~/Library/Logs/heavymailrule.log.

you double click it, and it should open beautifully in the log.

Try this first in a regular Applescript, so we know that we have it working.

you can use the handler like this in your mail rule script.

try
on error e number n
	my logit("An error ocurred while trying to fire off Display watcher:" & e & " " & n, "heavymailrule")
end try

Here is the handler.

to logit(log_string, log_file)
	do shell script ¬
		"echo `date '+%Y-%m-%d %T: '`\"" & log_string & ¬
		"\" >> $HOME/Library/Logs/" & log_file & ".log"
end logit

And .If everything we are doing now is failing for some reason, maybe because mail is “sandboxed”, then I have one more way of doing stuff, that will escape the “sandboxing” problems hopefully.

Awesome McUser,

I’ll try all of these with logs. Wish this wasn’t a problem that required an undetermined ‘long’ amount of time for real testing. I should be able to do this tonight.

Some misc. side questions: when defining a handler, “on” = “to” right? No functional difference there? I’ve used the Try block before, but what get’s returned to the variables before and after ‘number’ at the beginning of the On error block?

I’ll post some logs/results once I’ve run these.

Thanks,

Tim