Tell preview to get the window whose document is named "book.pdf" - applescript

I'm trying to get the window whose document has the name "book.pdf". Here's my approach
tell application "Preview"
set w to every window whose document is named "book.pdf"
end
This doesn't work. I've tried about 100 permutations but I'm not getting anywhere. Any tips?

You can use AXTitle combined with contains, and tell System Events not Preview
Note I have it wrapped in a try block because myWindow will be undefined if no string match is found.
set n to "book.pdf" -- whatever substring you want to find
tell application "System Events" to tell process "Preview"
try
set myWindow to (1st window whose value of attribute "AXMain" is true and value of attribute "AXTitle" contains n)
log myWindow
on error
log "not found"
end try
end tell

Related

Print result from two functions to console

I've created a small script to get the current size and position of a window. Unfortunately, I only can get one result at a time and need to comment/uncomment the other one.
tell application "System Events" to tell process "Toggl Track"
# get position of window 1
get size of window 1
end tell
If I uncomment both, I will only get the size.
So, my I tried to write the results in a variable and then log these instead.
tell application "System Events" to tell process "Toggl Track"
set position to get position of window 1
set size to get size of window 1
log position & size
end tell
With this, I get no result at all.
What did I do wrong?
position and size are part of the terminology of System Events. You cannot use them as variable names. Rename the variables
tell application "System Events" to tell process "Toggl Track"
set windowPosition to position of window 1
set windowSize to size of window 1
log windowPosition & windowSize
end tell
Regarding the first script, get saves the result of the line in the AppleScript property result and overwrites previous values.

How to get/set applescript property from string?

I'm trying to automate the position of my dock in MacOS with applescript.
I can successfully position the dock. This works perfectly:
tell application "System Events"
tell dock preferences
set properties to {screen edge:right}
end tell
end tell
The problem is that I want to accept the position as an argument, and it's provided as a string. So I end up with the equivalent of:
tell application "System Events"
tell dock preferences
set x to "right"
set properties to {screen edge:x}
end tell
end tell
This results in an error:
"System Events got an error: Can\U2019t make \"right\" into type constant.";
How do I 'resolve' my string into the constant that is expected?
right (without quotes) is an integer value, an enumerated constant. You cannot cast a string to an enum.
If you really need a string argument a workaround is an if - else chain
on setDockScreenEdge(theEdge)
tell application "System Events"
tell dock preferences
if theEdge is "right" then
set screen edge to right
else if theEdge is "left" then
set screen edge to left
else if theEdge is "bottom" then
set screen edge to bottom
end if
end tell
end tell
end setDockScreenEdge
Then you can change the edge with a string argument
setDockScreenEdge("right")
It's not necessary to set the properties record. You can set a single property directly

How to get name of frontmost app with AppleScript and use it to get the filepath

What I try to do:
When I'm in one of my text editors (TextEdit, Byword, FoldingText) I want this AppleScript to display the file path.
I figured asking for the frontmost window app get's me the apps name nice and easily and then I can ask for the POSIX path in the next step.
The Problem:
The script is already 99% there, but I'm missing something. When I try to use the variable of activeApp it doesn't work and I get this error:
Error Number:System Events got an error: Can’t get application {"TextEdit"}.
-1728
Here's the script:
tell application "System Events"
set activeApp to name of application processes whose frontmost is true
--This doesn't work either:
--do shell script "php -r 'echo urldecode(\"" & activeApp & "\");'"
tell application activeApp
set myPath to POSIX path of (get file of front document)
end tell
display dialog myPath
end tell
If I exchange activeApp with "TextEdit" everything works. Help would be appreciated.
Maybe there's something in here that helps: Get process name from application name and vice versa, using Applescript
Either get the path property of a document or use System Events to get value of attribute "AXDocument":
try
tell application (path to frontmost application as text)
(path of document 1) as text
end tell
on error
try
tell application "System Events" to tell (process 1 where frontmost is true)
value of attribute "AXDocument" of window 1
end tell
do shell script "x=" & quoted form of result & "
x=${x/#file:\\/\\/}
x=${x/#localhost} # 10.8 and earlier
printf ${x//%/\\\\x}"
end try
end try
The first method didn't work with Preview, TextMate 2, Sublime Text, or iChm, and the second method didn't work with Acorn. The second method requires access for assistive devices to be enabled.
You are asking for...
set activeApp to name of application processes whose frontmost is true
Notice "processes", that's plural meaning you can get several processes in response so applescript gives you a list of names. Even though only one application is returned it's still in list format. Also see that your error contains {"TextEdit"}. The brackets around the name mean it's a list, so the error is showing you the problem.
You can't pass a list of names to the next line of code. As such you have a couple of choices. 1) you can ask for only 1 process instead of all processes. That will return a string instead of a list. Try this code...
set activeApp to name of first application process whose frontmost is true
2) you can work with the list by using "item 1 of the list". Try this code...
set activeApps to name of application processes whose frontmost is true
set activeApp to item 1 of activeApps
Finally, you shouldn't be telling system events to tell the application. Separate those 2 tell blocks of code. Here's how I would write your code.
tell application "System Events"
set activeApp to name of first application process whose frontmost is true
end tell
try
tell application activeApp
set myPath to POSIX path of (get file of front document)
end tell
tell me
activate
display dialog myPath
end tell
on error theError number errorNumber
tell me
activate
display dialog "There was an error: " & (errorNumber as text) & return & return & theError buttons {"OK"} default button 1 with icon stop
end tell
end try
I can't promise the "get file of front document" code will work. That depends on the application. Not all applications will understand that request. That's why I used a try block. In any case though you can be certain you are addressing the proper application. Good luck.
I've been using this snippet for a while, seems to work for all Cocoa apps (not sure about X11):
set front_app to (path to frontmost application as Unicode text)
tell application front_app
-- Your code here
end tell
None of this seems to work with a compiled AppleScript saved as an application and placed on the Dock. Whenever you run the application, IT is the frontmost, not the application that is showing its front window. That application becomes inactive as my Applescript runs. How do I write an Applescript application that isn't active when it runs?
I may have found a solution to the problem listed above. Just tell the user to reactivate the desired application, and give them time.
tell application "Finder"
activate
say "Click front window of your application"
delay 5
set myapp to get name of first application process whose frontmost is true
-- etc.
-- your code
end tell

IF Statesment using AppleScript

I'm trying to different events depending on what application is currently the "open" application - The one which is foremost of the screen. I have managed to save the name of the application using a variable. Using this code.
tell application "System Events"
item 1 of (get name of processes whose frontmost is true)
set openWindow to (get name of processes whose frontmost is true)
do shell script "echo " & openWindow & " > /Users/name/temp/currentWindow.txt"
end tell
I then tried to use this code do different events for each open application
tell application "System Events"
if openWindow = "AppleScript Editor" then
display dialog "my variable: " & openWindow
end if
end tell
However this code does not apper to do anything, I don't have any error messages or anything however the code doesn't display the dialog box. If I place the code for the dialog box in the first section of code it will display the name of the open application.
Any ideas on how to get this to work, it would be very helpful
To explain your problem, it's because of this code...
set openWindow to (get name of processes whose frontmost is true)
That code returns a list of items. Notice you asked for processes (plural), so you can get more than one so applescript gives it to you as a list whether there's one or more items found. What's strange is that in the line above this you do ask for "item 1" of the list but for some reason you don't do anything with that line of code. Normally I would write that line of code like this so I only get item 1...
set openWindow to name of first process whose frontmost is true
Anyway, you can't compare the string "AppleScript Editor" to a list {"AppleScript Editor"}. They are not equal so your if statement is never true.
Display dialog displays a string. So when you move that code outside the if statement, applescript is smart enough to convert your list into a string so it can be displayed.
So bottom line is you are getting a list and you must access the items of the list. The items are strings so get one (in your case you want item 1) and use that in the if statement.
Hopefully you can learn from this explanation. Good luck.
In the first script cast the openWindow variable to a string:
set openWindow to (get name of processes whose frontmost is true) as string

Class based selectors for AppleScript list items failing for UI element objects

AppleScript’s list data type has only a very limited support for boolean test specifiers. Besides picking items by range (with the item keyword), specifying a class will work:
get every «class furl» of {1, "Test", (POSIX file "/posix/path")} --> {file ":hfs:path"}
When the list items are references, dereferencing with the contents keyword will work:
get every «class furl» of {1, "Test", a reference to (POSIX file "/posix/path")} --> {}
get every «class furl» of contents of {1, "Test", a reference to (POSIX file "/posix/path")} --> {file ":hfs:path"}
So why does the following code set allTextAreas to an empty list:
tell application "System Events"
set allUIElements to entire contents of window 1 of someApplication
set allTextAreas to every text area of contents of allUIElements --> {}
end tell
given that allUIElements is a list of references to UI element objects, and that at least one of them is of class text area?
Note I am not looking for suggestions how to retrieve all UI elements of a certain type from the list (a repeat loop will do that) – I would like to understand why the selector pattern fails in this specific case.
Here's how I would do it if I wanted to find all the buttons of the front window in Safari. Just apply this logic to your situation.
tell application "System Events"
tell process "Safari"
set allButtons to UI elements of window 1 whose class is button
end tell
end tell
Getting the UI elements from the application results in a list of object specifiers: application objects (a form of nested containers) where each item in the hierarchy has several properties, including a class – Technical Note TN2106 might shed more light on this –, while your first example used a file URL (a type of file reference) which has a base class.
So you will need to use either an application filter reference form when getting the objects from the application or query the desired properties of the returned objects, for example:
set allButtons to {}
tell application "System Events" to tell application process "Safari"
set allUIElements to entire contents of window 1
repeat with anElement in allUIElements
try
if class of anElement is button then set end of allButtons to contents of anElement
end try
end repeat
end tell
allButtons

Resources