Jump to content

Applescript runs differently in Alfred and in Applescript Editor


Recommended Posts

I took Runar's Open in Chrome workflow and made a new version which (theoretically) behaves a bit more intelligently in situations where Safari either isn't open, or doesn't have any windows open, and which posts slightly more informative notifications. The Applescript I wrote behaves exactly as intended when run from Applescript Editor, but not when run from Alfred. If Safari isn't open it ought to simply post a notification saying as much, but the Alfred version always opens Safari in the background first.

Workflow: Open in Chrome
Keyword: openinchrome
Hotkey: alt+g

 

if application "Safari" is running then
	tell application "Safari"
		try
			set theURL to URL of current tab of window 1
			set pageName to name of current tab of window 1
		on error
			return "There are no pages open in Safari at the moment"
		end try
	end tell
	
	tell application "Google Chrome"
		activate
		if (count of windows) is 0 then make new window
		set URL of active tab of front window to theURL
	end tell
	
	# Enable this line to have notifications posted after sending URLs to Chrome
	#return "Opening '" & pageName & "' in Chrome"
else
	return "Safari is not open at the moment"
end if

 

 

Link to comment

I took Runar's Open in Chrome workflow and made a new version which (theoretically) behaves a bit more intelligently in situations where Safari either isn't open, or doesn't have any windows open, and which posts slightly more informative notifications. The Applescript I wrote behaves exactly as intended when run from Applescript Editor, but not when run from Alfred. If Safari isn't open it ought to simply post a notification saying as much, but the Alfred version always opens Safari in the background first.

Workflow: Open in Chrome

Keyword: openinchrome

Hotkey: alt+g

 

if application "Safari" is running then
	tell application "Safari"
		try
			set theURL to URL of current tab of window 1
			set pageName to name of current tab of window 1
		on error
			return "There are no pages open in Safari at the moment"
		end try
	end tell
	
	tell application "Google Chrome"
		activate
		if (count of windows) is 0 then make new window
		set URL of active tab of front window to theURL
	end tell
	
	# Enable this line to have notifications posted after sending URLs to Chrome
	#return "Opening '" & pageName & "' in Chrome"
else
	return "Safari is not open at the moment"
end if

 

wow, thats interesting. I've tinkered with this a bit this morning and can replicate what your talking about.

 

When run in ASE, if Safari isn't open, it will simply return that it's not open. In Alfred, it will launch Safari (background) and Chrome. It's like it's not respecting the if statement. It drops in there regardless of the running state. I'm going to keep messing with a it a bit and see if I can come up with something.

Link to comment

After playing around for a bit I discovered that the script runs exactly as intended if included via the NSApplescript action. Perhaps due to what Andrew refers to as "security" restrictions on osascript? http://www.alfredforum.com/topic/1862-nsapplescript-vs-run-script/?p=9838

 

 

EDIT: Turns out there's more to it than that. Here's what I did, and what I found.

 

Ran via Run Script - Behaviour still not as expected

Ran via NSApplescript - Behaviour still not as expected

Ran once via NSApplescript with caching - Behaviour still not as expected

Ran a second time via NSApplescript with caching - Works perfectly

Ran a bunch more times via NSApplescript with caching - Works perfectly

Restart Alfred and run again - Behaviour not as expected the first time

Run a bunch more times - Works perfectly

 

So once the script has been cached it appears to work as expected.

Edited by Subject22
Link to comment

I took Runar's Open in Chrome workflow and made a new version which (theoretically) behaves a bit more intelligently in situations where Safari either isn't open, or doesn't have any windows open, and which posts slightly more informative notifications. The Applescript I wrote behaves exactly as intended when run from Applescript Editor, but not when run from Alfred. If Safari isn't open it ought to simply post a notification saying as much, but the Alfred version always opens Safari in the background first.

Workflow: Open in Chrome

Keyword: openinchrome

Hotkey: alt+g

 

if application "Safari" is running then
	tell application "Safari"
		try
			set theURL to URL of current tab of window 1
			set pageName to name of current tab of window 1
		on error
			return "There are no pages open in Safari at the moment"
		end try
	end tell
	
	tell application "Google Chrome"
		activate
		if (count of windows) is 0 then make new window
		set URL of active tab of front window to theURL
	end tell
	
	# Enable this line to have notifications posted after sending URLs to Chrome
	#return "Opening '" & pageName & "' in Chrome"
else
	return "Safari is not open at the moment"
end if

 

You may find that Safari can't resolve 'window 1' when it's not active as this will mean the currently focused window. Try adding an activate like you see in the google chrome bit.

Link to comment

Perhaps I haven't understood you correctly, but how would that help? The problem is that when Safari is not open the script fails to respect the if statement, causing Safari to launch. It ought to just return "Safari is not open at the moment" - which it does when the script is run from AppleScript Editor. I tried your suggestion, just in case. No luck :-/ If Safari's not open when I invoke the workflow it still launches, even though it should just post a notification.

 

EDIT: Whoops. I thought I was in a different thread D: Excuse me while I adjust my reply :-) Done.

Edited by Subject22
Link to comment

Carlos-Sz's version uses that exact method, if I recall correctly. But that still fails when run directly from Alfred, it has to be saved as a .scpt in the workflow's directory and called with a bash script.

 

EDIT: I lie. He tested a similar method, but neither way works properly when run from within Alfred. Both work fine from AppleScript Editor.

 

This isn't really relevant, but we might as well be looking at the same thing. Here's the version of the code I'm using at the moment. I got rid of references to window 1 and started using front window instead, along with some other slight improvements.

 

if application "Safari" is running then
	tell application "Safari"
		try
			set theURL to URL of current tab of front window
			set pageName to name of current tab of front window
		on error
			return "There are no pages open in Safari at the moment"
		end try
	end tell
	
	tell application "Google Chrome"
		activate
		
		if URL of active tab of front window is not theURL then
			if (count of windows) is 0 then
				make new window
			else
				make new tab at end of tabs of front window
			end if
			
			set URL of active tab of front window to theURL
		else
			return "The current Safari tab is already open in Chrome"
		end if
	end tell
	
	# Enable the following line to post notifications after sending URLs to Chrome
	--return "Opening '" & pageName & "' in Chrome"
else
	return "Safari is not open at the moment"
end if
Edited by Subject22
Link to comment

I am experiencing a similar problem with a separate Applescript created by Ben Waldie which creates completion reports from Omnifocus and deposits them in Evernote.  If run in the AppleScript editor you are prompted to select the time frame for the report, but thus far I have been unable to replicate this when using a workflow.  

 

The main reason for creating a workflow is that Evernote needs to be open in order for the script to run.  So basically I am trying to create a simple workflow which opens Evernote then runs the script.

 

-- This property controls whether full project paths (including parent folders) are displayed
property includeFullProjectPaths : true

-- These properties control whether additional task content is displayed
property includeTaskContext : true
property includeTaskEstimatedTime : true
property includeTaskStartDate : true
property includeTaskModificationDate : true
property includeTaskCompletionDate : true
property includeTaskNotes : true

-- This setting specifies a name for the new note
property theNoteName : "OmniFocus Completed Task Report"

-- Prompt the user to choose a scope for the report
activate
set theReportScope to choose from list {"Today", "Yesterday", "This Week", "Last Week", "This Month"} default items {"Yesterday"} with prompt "Generate a report for:" with title "OmniFocus Completed Task Report"
if theReportScope = false then return
set theReportScope to item 1 of theReportScope

-- Calculate the task start and end dates, based on the specified scope
set theStartDate to current date
set hours of theStartDate to 0
set minutes of theStartDate to 0
set seconds of theStartDate to 0
set theEndDate to theStartDate + (23 * hours) + (59 * minutes) + 59

if theReportScope = "Today" then
	set theDateRange to date string of theStartDate
else if theReportScope = "Yesterday" then
	set theStartDate to theStartDate - 1 * days
	set theEndDate to theEndDate - 1 * days
	set theDateRange to date string of theStartDate
else if theReportScope = "This Week" then
	repeat until (weekday of theStartDate) = Sunday
		set theStartDate to theStartDate - 1 * days
	end repeat
	repeat until (weekday of theEndDate) = Saturday
		set theEndDate to theEndDate + 1 * days
	end repeat
	set theDateRange to (date string of theStartDate) & " through " & (date string of theEndDate)
else if theReportScope = "Last Week" then
	set theStartDate to theStartDate - 7 * days
	set theEndDate to theEndDate - 7 * days
	repeat until (weekday of theStartDate) = Sunday
		set theStartDate to theStartDate - 1 * days
	end repeat
	repeat until (weekday of theEndDate) = Saturday
		set theEndDate to theEndDate + 1 * days
	end repeat
	set theDateRange to (date string of theStartDate) & " through " & (date string of theEndDate)
else if theReportScope = "This Month" then
	repeat until (day of theStartDate) = 1
		set theStartDate to theStartDate - 1 * days
	end repeat
	repeat until (month of theEndDate) is not equal to (month of theStartDate)
		set theEndDate to theEndDate + 1 * days
	end repeat
	set theEndDate to theEndDate - 1 * days
	set theDateRange to (date string of theStartDate) & " through " & (date string of theEndDate)
end if

-- Begin preparing the task list as HTML.
set theProgressDetail to "<html><body><h1>Completed Tasks</h1><br><b>" & theDateRange & "</b><br><hr><br>"

-- Retrieve a list of projects modified within the specified scope
set modifiedTasksDetected to false
tell application "OmniFocus"
	tell front document
		set theModifiedProjects to every flattened project where its modification date is greater than theStartDate and modification date is less than theEndDate
		-- Loop through any detected projects
		repeat with a from 1 to length of theModifiedProjects
			set theCurrentProject to item a of theModifiedProjects
			-- Retrieve any project tasks modified within the specified scope
			set theCompletedTasks to (every flattened task of theCurrentProject where its completed = true and modification date is greater than theStartDate and modification date is less than theEndDate and number of tasks = 0)
			-- Process the project if tasks were found
			if theCompletedTasks is not equal to {} then
				set modifiedTasksDetected to true
				-- Append the project folder path to the project name
				set theProjectFolderPath to ""
				if includeFullProjectPaths = true then
					set theProjectFolderPath to getProjectFolderPath(theCurrentProject) of me
					if theProjectFolderPath is not equal to "" then set theProjectFolderPath to theProjectFolderPath & " > "
				end if
				-- Append the project name to the report
				set theProgressDetail to theProgressDetail & "<h2>" & theProjectFolderPath & name of theCurrentProject & "</h2>" & return & "<br><ul>"
				-- Loop through the detected tasks for the project
				repeat with b from 1 to length of theCompletedTasks
					set theCurrentTask to item b of theCompletedTasks
					-- Append the tasks's name to the task list
					set theProgressDetail to theProgressDetail & "<li>" & name of theCurrentTask
					-- Set up a variable for the task detail, if relevant
					set theTaskDetail to ""
					-- Append the context to the task detail
					if includeTaskContext = true then
						set theContext to context of theCurrentTask
						if theContext is not equal to missing value then set theTaskDetail to appendTaskDetail(theTaskDetail, name of theContext, "Context", "") of me
					end if
					-- Append the estimated time to the task detail
					if includeTaskEstimatedTime = true then set theTaskDetail to appendTaskDetail(theTaskDetail, estimated minutes of theCurrentTask, "Estimated Time", " minutes") of me
					-- Append the start date to the task detail
					if includeTaskStartDate = true then set theTaskDetail to appendTaskDetail(theTaskDetail, start date of theCurrentTask, "Start Date", "") of me
					-- Append the modification date to the task detail
					if includeTaskStartDate = true then set theTaskDetail to appendTaskDetail(theTaskDetail, modification date of theCurrentTask, "Modification Date", "") of me
					-- Append the completion date to the task detail
					if includeTaskStartDate = true then set theTaskDetail to appendTaskDetail(theTaskDetail, completion date of theCurrentTask, "Completion Date", "") of me
					-- Append the task's notes to the task detail
					if includeTaskNotes = true then set theTaskDetail to appendTaskDetail(theTaskDetail, note of theCurrentTask, "Note", "") of me
					-- Append the task detail to the task list
					if theTaskDetail is not equal to "" then
						set theProgressDetail to theProgressDetail & "<br><p style=\"color: gray\">" & theTaskDetail & "</p>"
					end if
					-- Finish adding the task's HTML to the list
					set theProgressDetail to theProgressDetail & "</li>" & return
				end repeat
				set theProgressDetail to theProgressDetail & "</ul>" & return
			end if
		end repeat
	end tell
end tell
set theProgressDetail to theProgressDetail & "</body></html>"

-- Notify the user if no projects or tasks were found
if modifiedTasksDetected = false then
	display alert "OmniFocus Completed Task Report" message "No modified tasks were found for " & theReportScope & "."
	return
end if

-- Create the note in Evernote.
tell application "Evernote"
	activate
	set theNote to create note notebook "Inbox" title theNoteName with html theProgressDetail
	open note window with theNote
end tell

-- This handler gets the folder path for a project
on getProjectFolderPath(theProject)
	tell application "OmniFocus"
		set theFolderPath to ""
		if folder of theProject exists then
			set theFolder to folder of theProject
			repeat
				if theFolderPath is not equal to "" then set theFolderPath to " : " & theFolderPath
				set theFolderPath to name of theFolder & theFolderPath
				if class of container of theFolder = folder then
					set theFolder to container of theFolder
				else
					exit repeat
				end if
			end repeat
		end if
		if theFolderPath = "" then set theFolderPath to ""
		return theFolderPath
	end tell
end getProjectFolderPath

-- This handler appends a value to the task detail
on appendTaskDetail(theTaskDetail, theValue, thePrefix, theSuffix)
	if theTaskDetail is not equal to "" then set theTaskDetail to theTaskDetail & "<br>"
	if theValue = missing value or theValue = "" then
		set theValue to "N/A"
	else
		set theValue to theValue & theSuffix
	end if
	return theTaskDetail & thePrefix & ": " & theValue
end appendTaskDetail
Link to comment

I haven't read through all that exhaustively, but it seems to me that you're running the script and *then* opening Evernote, and you mentioned that Evernote needs to be open in order for the script to run. Have you tried moving the code for opening Evernote to the start of the script?

Link to comment

Subject 22.  Thanks for the suggestion.  I added tell application "Evernote" activate end tell to the beginning of the script, but it doesn't help.  In Applescript editor I first have to manually open Evernote before the script will compile.  Without Evernote open it says there is a syntax error "expected end of line, etc. but found application constant or consideration" in line 133 with note highlighted.  I was trying to create a simple workflow where i could first open evernote and then run the script.  I got evenote to open, but the script doesn't run.  

 

I am new to all this so any help is much appreciated. 

Link to comment

OK, I'd suggest making a new thread in Workflow Help & Questions about this, since your problem seems a little unrelated at this point (given that the script's misbehaving in AppleScript Editor. You'll probably get more people's attention that way :-) I have a couple of vague ideas which may or may not help, but I'll hold off posting those for now.

Link to comment

Hi Andrew,

 

Could the problem be caused by Alfred compiling the script? If you compile the script below in AppleScript without Safari running, it will launch upon compliation.

tell application "Safari"
    set URL of document 1 to "http://www.alfredforum.com/"
end tell
Link to comment
  • 1 year later...

Try running this bash script, it will recompile all .scpt files inside ~/Library/Application\ Support/Alfred\ 2/Alfred.alfredpreferences/workflows

cd ~/Library/Application\ Support/Alfred\ 2/Alfred.alfredpreferences/workflows
for f in user.workflow.*/*.scpt; do
    plaintext=$(osadecompile "$f")
    # | sponge |
    echo "$plaintext" | osacompile -o "$f"
    echo "Recompiled $f"
done

Edited by Tyilo
Link to comment
  • 3 weeks later...

 

Try running this bash script, it will recompile all .scpt files inside ~/Library/Application\ Support/Alfred\ 2/Alfred.alfredpreferences/workflows

cd ~/Library/Application\ Support/Alfred\ 2/Alfred.alfredpreferences/workflows
for f in user.workflow.*/*.scpt; do
    plaintext=$(osadecompile "$f")
    # | sponge |
    echo "$plaintext" | osacompile -o "$f"
    echo "Recompiled $f"
done

Thanks for this! If I get a chance I'll come back to it Appreciate the help!

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...