I run a screen which display some data on the menu bar
the variables are taken from "~/Desktop/_MyData.plist"
everything work fine, however when the data change on _MyData.plist
How, can I make the script getting the new data ? I guess we can't expect AppleScript to detect file change and then run the script but is there a way to get the plist data on idle maybe and keeping running the whole script.
Here is the part that only getting the data :
property theAccountNumberFromPlist : ""
property SNNumber : ""
property appName : ""
property devicesID : ""
property domainEMAIL : ""
property fullEmail : ""
property purchaseDate : ""
property thename : ""
property theList : ""
set the plistfile_path to "~/Desktop/_MyData.plist.plist"
tell application "System Events"
set p_list to property list file (plistfile_path)
-- read the plist data
set theAccountNumberFromPlist to value of property list item "AccountNumber" of p_list as text
set SNNumber to value of property list item "SNNUMBER" of p_list as text
set appName to value of property list item "appName" of p_list as text
set devicesID to value of property list item "devicesID" of p_list as text
set domainEMAIL to value of property list item "domainEMAIL" of p_list as text
set fullEmail to value of property list item "fullEmail" of p_list as text
set purchaseDate to value of property list item "purchaseDate" of p_list as text
set thename to value of property list item "thename" of p_list as text
end tell
Here is the whole script :
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property StatusItem : missing value
property selectedMenu : ""
property theDisplay : ""
property defaults : class "NSUserDefaults"
property internalMenuItem : class "NSMenuItem"
property externalMenuItem : class "NSMenuItem"
property newMenu : class "NSMenu"
property theAccountNumberFromPlist : ""
property SNNumber : ""
property appName : ""
property devicesID : ""
property domainEMAIL : ""
property fullEmail : ""
property purchaseDate : ""
property thename : ""
property theList : ""
set the plistfile_path to "~/Desktop/_MyData.plist.plist"
tell application "System Events"
set p_list to property list file (plistfile_path)
-- read the plist data
set theAccountNumberFromPlist to value of property list item "AccountNumber" of p_list as text
set SNNumber to value of property list item "SNNUMBER" of p_list as text
set appName to value of property list item "appName" of p_list as text
set devicesID to value of property list item "devicesID" of p_list as text
set domainEMAIL to value of property list item "domainEMAIL" of p_list as text
set fullEmail to value of property list item "fullEmail" of p_list as text
set purchaseDate to value of property list item "purchaseDate" of p_list as text
set thename to value of property list item "thename" of p_list as text
end tell
if not (current application's NSThread's isMainThread()) as boolean then
display alert "This script must be run from the main thread." buttons {"Cancel"} as critical
error number -128
end if
on menuNeedsUpdate:(menu)
my makeMenus()
end menuNeedsUpdate:
on makeMenus()
newMenu's removeAllItems()
repeat with i from 1 to number of items in someListInstances
set this_item to item i of someListInstances
set thisMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:this_item action:"someAction:" keyEquivalent:"")
(newMenu's addItem:thisMenuItem)
(thisMenuItem's setTarget:me) -- required for enabling the menu item
if i is equal to 3 then
(newMenu's addItem:(current application's NSMenuItem's separatorItem)) -- add a seperator
end if
end repeat
end makeMenus
on someAction:sender
--MenuItem
end someAction:
-- create an NSStatusBar
on makeStatusBar()
set bar to current application's NSStatusBar's systemStatusBar
set StatusItem to bar's statusItemWithLength:-1.0
-- set up the initial NSStatusBars title
StatusItem's setTitle:(theAccountNumberFromPlist & " " & thename & " " & fullEmail & " " & SNNumber & " " & appName)
-- set up the initial NSMenu of the statusbar
set newMenu to current application's NSMenu's alloc()'s initWithTitle:"Custom"
newMenu's setDelegate:me (*
*)
StatusItem's setMenu:newMenu
end makeStatusBar
my makeStatusBar()
Make use of an idle handler.
on idle
-- do your stuff
return 5 -- idle handler will be executed again in 5 seconds.
end
Therefore you need to save your script as application. Here's the essential part from apples docs:
idle and quit Handlers for Stay-Open Applications
By default, a script application that receives a run or open command
handles that single command and then quits. In contrast, a stay-open
script application (one saved as Stay Open in Script Editor) stays
open after it is launched.
A stay-open script application can be useful for several reasons:
Stay-open script applications can receive and handle other commands in
addition to run and open. This allows you to use a script application
as a script server that, when it is running, provides a collection of
handlers that can be invoked by any other script.
Stay-open script applications can perform periodic actions, even in
the background, as long as the script application is running.
Two particular handlers that stay-open script applications often
provide are an idle handler and a quit handler.
idle Handlers
If a stay-open script application includes an idle handler,
AppleScript sends the script application periodic idle commands—by
default, every 30 seconds—allowing it to perform background tasks when
it is not performing other actions.
If an idle handler returns a positive number, that number becomes the
rate (in seconds) at which the handler is called. If the handler
returns a non-numeric value, the rate is not changed. You can return 0
to maintain the default delay of 30 seconds.
For example, when saved as a stay-open application, the following
script beeps every 5 seconds:
on idle
beep
return 5
end idle
The result returned from a handler is just the result of the last statement, even if it doesn’t include the word return explicitly.
Related
I can't change the "AXFrontmost" attribute value to false
As you can see, this code generates a loop
tell application "System Events"
set front_process to name of first process whose frontmost is true
tell process front_process
try
repeat while (value of attribute "AXFrontmost") is true
set value of attribute "AXFrontmost" to false
end repeat
on error
get properties of attribute "AXFrontmost"
end try
end tell
end tell
And in relation to the attribute property "AXFrontmost", the value of settable is true
The methods I found to FORCE the frontmost to false are toggling the visible status:
repeat while (value of attribute "AXFrontmost") is true
set visible to false
delay 0.01
set visible to true
end repeat
And the other way is using CMD + TAB key codes:
repeat while (value of attribute "AXFrontmost") is true
key code 48 using command down
end repeat
So, Why does this behavior occur ? given that the settable property is true.
Are there any other ways to force the value of attribute "AXFrontmost" to false? Besides the ones I already mentioned above?
Well, only one process can be frontmost.
For this, i would just « tell application Finder to activate »
This should set frontmost flag to false for every process.
To set Finder’s flag to false, « tell me to activate » should work.
I have two questions with my applescript. The script is supposed to send a dropped file as attachment by email and asking the object of the mail from a list.
The content of the message MUST be empty.
1) How to set an "empty" email signature because the content of my mail should be empty. I receive an error code "error in mail impossible to solve signature..."
2) I wish that the user can modify the value list {"00111111111111-number1, "0011111111111-number2"...} and add more numbers. What is the best approach to do this ?
Thanks very much in advance for your suggestions.
property theSubject : "subject"
property theNumber : ""
property theContent : ""
property theSignature : "none"
property onRun : ""
on run
tell application "Finder"
set sel to (get selection)
end tell
set onRun to 1
new_mail(sel)
end run
on open droppedFiles
new_mail(droppedFiles)
end open
on new_mail(theFiles)
set chosen to choose from list {"0011111111111-number1", "0011111111111-number2"} with prompt "Thanks to select"
if chosen is false then return "" -- in case of 'Cancel' return empty string
set theNumber to text 1 thru 13 of (item 1 of chosen) -- as chosen returns a list by default it must be flattened
tell application "Mail"
set newMessage to make new outgoing message with properties {visible:true, subject:theNumber}
tell newMessage
make new to recipient with properties {address:faxboxEmail}
if onRun < 1 then
make new attachment with properties {file name:theFiles as alias} at after last paragraph
end if
set the content to theContent
set message signature of newMessage to signature theSignature
end tell
activate
if onRun < 1 then
send
end if
end tell
end new_mail
to add new item in the list, may be this could help you ?
set BaseList to {"0011111111111-number1", "0011111111111-number2"}
set CList to BaseList & {"Add new item"}
set chosen to choose from list CList with prompt "Thanks to select"
if chosen is false then return "" -- in case of 'Cancel' return empty string
if "Add new item" is in chosen then
set OKNew to false
repeat until OKNew
set NewItem to display dialog "Enter new value :" default answer ""
set OKNew to (button returned of NewItem is "OK") and (text returned of NewItem is not "")
set theNumber to text returned of NewItem
set BaseList to baseList & {theNumber} -- to add the new item in the BaseList
end repeat
else
set theNumber to text 1 thru 13 of (item 1 of chosen) -- as chosen returns a list by default it must be flattened
end if
I also experienced some issues with the signature and the attachement together. if you remove the line "make new attachment..." the signature line is working. Also if you move the signature line before the attachement line, and make a break before the attachement, the signature will be OK. bug ?
Then, based on my tests, if you do not want signature at all, just delete the line "set message signature..." by default, no signature will be set.
My last comment is to reduce your script by adding the content directly in property list of the "make new outgoing message..."
tell application "Mail"
set newMessage to make new outgoing message with properties {visible:true, subject:TheNumber, content:TheContent}
tell newMessage
make new to recipient with properties {address:faxboxmail}
if onRun > 1 then
make new attachment with properties {file name:theFile as alias} at after last paragraph
end if
end tell
activate
end tell
I tried it, and it is creates mail with no content and no signature as expected (Mail 8.2)
I've got the following which displays two text input prompts and then queries for PPTP VPN configs and asks the user to 'choose from list'. The results are then saved to a plist file however vpn_name is always encoded inside of two blank arrays. I've tried setting the datatype of vpn_name to string but the same applies.
How can I get this to encode simply as:
<dict>
<key>password</key>
<string>fnkdslfsd</string>
<key>username</key>
<string>fnsdkfnds</string>
<key>vpn_name</key>
<string>SAMSUNG_Android</string>
</dict>
as opposed to how it's currently encoding:
<dict>
<key>password</key>
<string>fnkdslfsd</string>
<key>username</key>
<string>fnsdkfnds</string>
<key>vpn_name</key>
<array>
<array>
<string>SAMSUNG_Android</string>
</array>
</array>
</dict>
Applescript:
property key_path : "~/Library/Preferences/vpn-keys.plist"
property user_name : ""
property pass_word : ""
property vpn_name : ""
tell application "Finder"
if user_name is "" then
set dialog_1 to display dialog "Please enter your server username: " default answer ""
set the user_name to the text returned of dialog_1
end if
if pass_word is "" then
set dialog_2 to display dialog "Please enter your server password: " default answer ""
set the pass_word to the text returned of dialog_2
end if
if vpn_name is "" then
tell application "System Events"
tell current location of network preferences
set VPN_list to get name of every service whose (kind is greater than 11 and kind is less than 17)
end tell
end tell
vpn_name as string
set vpn_name to {choose from list VPN_list with prompt "Select Office VPN"}
end if
tell application "System Events"
set the parent_dictionary to make new property list item with properties {kind:record}
set the plistfile_path to key_path
set this_plistfile to ¬
make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:string, name:"username", value:user_name}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:string, name:"password", value:pass_word}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:string, name:"vpn_name", value:vpn_name}
end tell
end tell
choose from list returns a list of items selected and returns false when canceled. You defined an empty string before choose from list command is invoked but in AppleScript that doesn't have any effect between lines. So what you can do is test if the results are false before continuing because unlike a display dialog the script continues when the user pressed the cancel button. Then set value of new property list item to item 1 of vpn_name.
property key_path : "~/Library/Preferences/vpn-keys.plist"
property user_name : ""
property pass_word : ""
property vpn_name : ""
tell application "Finder"
if user_name is "" then
set dialog_1 to display dialog "Please enter your server username: " default answer ""
set the user_name to the text returned of dialog_1
end if
if pass_word is "" then
set dialog_2 to display dialog "Please enter your server password: " default answer ""
set the pass_word to the text returned of dialog_2
end if
if vpn_name is "" then
set vpn_name to false
tell application "System Events"
tell current location of network preferences
set VPN_list to get name of every service whose (kind is greater than 11 and kind is less than 17)
end tell
end tell
set vpn_name to choose from list VPN_list with prompt "Select Office VPN"
if vpn_name is false then return --stop, user pressed cancel
end if
tell application "System Events"
set the parent_dictionary to make new property list item with properties {kind:record}
set the plistfile_path to key_path
set this_plistfile to ¬
make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:string, name:"username", value:user_name}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:string, name:"password", value:pass_word}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:string, name:"vpn_name", value:item 1 of vpn_name}
end tell
end tell
I'm getting this error after exporting my script as an application. When running the script in script editor it works fine. But when running the application I get his error
Can't make item 1 of <> into type string
here is the code I have for it.
set deptList to {"basketball", "football", "golf", "compliance"}
(choose from list deptList)
if result is not false then
set dept_name to item 1 as string
else
display dialog "Operation Cancelled"
error number -128
Try using:
set dept_name to text of result
Applescript knows it's a string (or text) already, so we just need to tell it to set the variable dept_name to the text of the result.
tell application "Finder"
set deptList to {"basketball", "football", "golf", "compliance"}
(choose from list deptList)
if result is not false then
set dept_name to text of result
else
display dialog "Operation Cancelled"
error number -128
end if
display dialog dept_name
end tell
Choose from list has nothing to do with the Finder. Also, there is no text of result. There is a text returned of result but that is "present only if ‘default answer’ was supplied" with a dialog. Lastly, you should avoid using "result" altogether and assign the response to a variable.
set deptList to {"basketball", "football", "golf", "compliance"}
set dept_name to choose from list deptList with title "Insert your Title" with prompt "Insert your prompt" without multiple selections allowed
if dept_name is false then
error number -128
else
set dept_name to first item of dept_name
end if
Here is an example where using text returned of result would be applicable:
display dialog "Enter text" default answer "My text" buttons {"Cancel", "OK"} default button 2
return the result
tell application "VoodooPad"
tell document 1
repeat with thisPage from 1 to number of items in pages
set theName to display name of page thisPage
set creationDate to created of page thisPage
set theText to text of page thisPage
tell application "Evernote"
create note with text theText title theName notebook "VoodooPad Imported Notes" tags "imported_from_VoodooPad" created creationDate
end tell
end repeat
end tell
end tell
This produces the following error:
error "VoodooPad got an error: every item of every page of document 1 doesn’t understand the count message." number -1708 from every item of every page of document 1
Any Idea on how to get the script to run?
Try this:
set allPages to pages as list // now you have items in a list
repeat with thisPage from 1 to number of items in allPages
...