d-b
d-b

Reputation: 971

Applescript and Automator - Safari gets stuck and I have to push Esc to continue

This simple Applescript works as expected:

tell application "Safari"
    activate
    set theURL to URL of front document
end tell

I now try to make an Automator action/service of it:

on run {input, parameters}
    tell application "System Events"
        if (name of the first process whose frontmost is "true") is "Safari" then
            set theURL to URL of front document
        end if
    end tell
    return theURL
end run

but that returns an error message:

The action “Run AppleScript” encountered an error: “System Events got an error: Can’t get URL of document 1.”

Hmm, so I add a tell application "Safari" to activate in Automator to make sure it really is Safari who receives these commands:

on run {input, parameters}
    tell application "System Events"
        if (name of the first process whose frontmost is "true") is "Safari" then
            tell application "Safari"
                activate
                set theURL to URL of front document
            end tell
        end if
    end tell
    return theURL
end run

Weird, now the Automator action gets stuck on 0 % (as seen in the Automator cog wheel in the menu bar). To make the script finish I have to push Esc.

In fact, if I switch out of Safari when stuck at 0 % Safari remains backgrounded when I try to switch back to it until I press Esc. After pressing Esc Safari automatically is foregrounded and the Automator action finishes.

That is:

  1. Select some text in Safari and select this service from the contextual menu.
  2. Service gets stuck at 0 %.
  3. Switch to another application A. This works as expected. Service is still stuck at 0 %.
  4. Try to switch back to Safari using cmd-tab, dock or something else. Nothing happens, A is still in the foreground and the service is stuck at 0 %.
  5. Press Esc. Now the service finishes and Safari becomes foregrounded.

Finally, I have set the Automator action to replace

So, why can't I access the URL in the first version? And why does it get stuck in the second version? How should I write this to accomplish what I want?

Edit: to clarify what I am trying to achieve. I want to get the URL from the frontmost window in Safari, process the URL and then use it somewhere else. I have removed the processing and "somewhere else" part of my Automator workflow to simplify the question.

Upvotes: 0

Views: 640

Answers (2)

RobC
RobC

Reputation: 25042

You can do something like the following to ascertain the URL and which app/browser the URL came from.

The code in the following gist is intentionally verbose for ease of understanding, and besides I don't know exactly what you want to achieve. However it acts to provide you with the general gist to achieve what you're wanting to do.

It does the following:

  1. Gets the name of the frontmost application.
  2. When the frontmost app is either Safari or Google Chrome it will firstly check that a window is available.
    • If a window is not available it will notify the user.
    • If a window is available it will display a dialog indicating the URL and the name of Browser it came from. This is just to demonstrate that the variables theURL and whichBrowser hold the info that you need.
  3. If the Service is not run from either Safari or Google Chrome it will notify the user that it must be run from either Safari or Google Chrome.

on run {input, parameters}

  tell application "System Events" to set theActiveApp to name of first process where it is frontmost

  set theURL to "unknown"
  set whichBrowser to "unknown"

  if theActiveApp is equal to "Safari" then
    tell application "Safari"
      if exists document 1 then
        set theURL to URL of current tab of window 1
        set whichBrowser to theActiveApp
      else
        display dialog "This service requires active window in Safari with a URL" & return & return & "Try opening a new window." with icon caution
        return
      end if
    end tell
  else if theActiveApp is equal to "Google Chrome" then
    tell application "Google Chrome"
      if exists window 1 then
        set theURL to URL of active tab of window 1
        set whichBrowser to theActiveApp
      else
        display dialog "This service requires active window in Chrome with a URL" & return & return & "Try opening a new window." with icon caution
        return
      end if
    end tell
  end if

  -- The Service was NOT run from either Safari or Google Chrome
  if theURL = "unknown" and whichBrowser = "unknown" then
    tell application "Finder"
      activate
      display dialog "This Service must be run from either Safari or Google Chrome" & theActiveApp with icon caution
    end tell
  else
    -- Report the results
    display dialog "The url is: " & theURL & return & return & "From app: " & theActiveApp
  end if

  -- ONLY return theURL to the next task if we've got it.
  if theURL ≠ "unknown" then
      return theURL
  end if

end run

Note

In the last part that reads:

if theURL ≠ "unknown" then
    return theURL
end if

This will cause the Workflow to stop running if theURL is not known (i.e. The service was not run from either Safari/Chrome or a window was not open in the browser). Otherwise it will pass theURL to the next Automator task.


Version of the script with only the necessary dialogs

This version below will only display the necessary dialogs and does not report theURL and whichBrowser variables in a dialog.

on run {input, parameters}

  tell application "System Events" to set theActiveApp to name of first process where it is frontmost

  set theURL to missing value

  if theActiveApp is equal to "Safari" then
    tell application "Safari"
      if exists document 1 then
        set theURL to URL of current tab of window 1
      else
        display dialog "This service requires active window in Safari with a URL" & return & return & "Try opening a new window." with icon caution
        return -- return early
      end if
    end tell
  else if theActiveApp is equal to "Google Chrome" then
    tell application "Google Chrome"
      if exists window 1 then
        set theURL to URL of active tab of window 1
      else
        display dialog "This service requires active window in Chrome with a URL" & return & return & "Try opening a new window." with icon caution
        return -- return early
      end if
    end tell
  end if

  if theURL is equal to missing value then
    -- The Service was NOT run from either Safari or Google Chrome
    tell application "Finder"
      activate
      display dialog "This Service must be run from either Safari or Google Chrome" & theActiveApp with icon caution
    end tell
  else
    -- ONLY return theURL to the next Automator task if we've got it.
    return theURL
  end if

end run

Upvotes: 1

vadian
vadian

Reputation: 285290

The error occurs because you are running Safari terminology in a System Events tell block which cannot work.

Actually it's not necessary to make Safari frontmost. This line should do the job.

on run {input, parameters}
    tell application "Safari" to return URL of front document
end run

A more robust version checks if the front document exists

on run {input, parameters}
    tell application "Safari"
        if exists document 1 then return URL of front document
        return missing value
    end tell
end run

If you are going to make a Automator service set Service receives to no input

Upvotes: 1

Related Questions