I have a system which move files across the network to my MAC computer (CSV File), that file is necessary for me to feed a local system, but sometimes people forget sending it or producing it, so I need to show an error message in my computer that says "Careful, there is not a file in your folder"
A POP UP would be good to have, this script should run every 2 seconds, it should show a button to close the message.
Any ideas on how to do this using applescripts? anyone have example code?
Something such as this might be what you are looking for:
set POSIXpath to "/path/of/file"
set POSIXfile to POSIXpath & "file.csv"
set theAlias to POSIX file POSIXfile
tell application "Finder"
repeat
--The next line is optional
if exists process "Application of CSV file" then
if not (exists theAlias) then
--display alert
display alert "Warning: the file does not exist"
end if
end if
delay 5
end repeat
end tell
The optional line I included can be made to check for the process of whatever application you are using the file with. So for example:
if exists process "Numbers" then
This checks first to see if the application "Numbers" was currently running. If you choose not to check the application process remove that line and one end if statement.
Related
I have many instances of VLC open. I want to check the playing status of every instance like:
tell application "VLC"
if playing = true then return
end tell
But it checks only one instance of VLC. How can I check all instances?
This is a workaround answer based on your comment "I want to prevent a scheduled applescript to execute if a VLC instance is playing." and the other information that has been presented in other comments and answer posted prior to this one. Also, by execute, I'm assuming you mean execute any additional code in the script that started on schedule.
Also note, this may not be perfect however its being presented to give it a try.
On my system, when an occurrence of VLC is open and without content loaded, after the initial percent of CPU usage spikes it quickly settles to 0% and with content loaded but not playing it's less than 5% and typically less than 3%. If it's playing it's typically always greater than 5%.
This of course may vary on your system, so you'll need to monitor over a period of time polling CPU usage to see how it fluctuates on your system to see what the sweet spot is.
The following example AppleScript code when placed at the beginning of the code in the scheduled AppleScript, prior to code in your script to trigger whatever with VLC, will abort processing the rest of the script if the percent of CPU usage of other instances of VLC is equal to or greater than 5%.
set |VLC%CPU| to paragraphs of text of ¬
(do shell script "ps -Ac -o %cpu -o command | grep [V]LC ; exit 0")
repeat with thisItem in |VLC%CPU|
if first word of thisItem as integer ≥ 5 then return
end repeat
Another method could be to rename the instances by making copies of the application, and giving them new names such as VLC1, VLC2. You can do this by going to the applications folder and copying the VLC Application. Then paste it within the same folder to create the app "VLC copy". Then rename each copy you create. The copies will now show in the applescript dictionaries.
You can now use a tell block for each instance to check if it's playing. You just need to make sure that you open the correct instance numbers for the number you have playing. E.g. don't open "VLC1" and "VLC3" if you only have 2 instances, or close a lower instance number. By having the if c is equal to statement it won't open that instance of the application by executing the tell block.
If you have all instances open you could remove the loop and the if statements and just check if they're playing or not.
on getCount()
tell application "System Events"
set p to processes whose name contains "VLC"
set theCount to count of p
return theCount
end tell
end getCount
set appCount to my getCount()
if appCount is greater than 0 then
repeat with c from 1 to appCount
if c is equal to 1 then
tell application "VLC1"
if playing is true then
log ("playing 1")
end if
end tell
end if
if c is equal to 2 then
tell application "VLC2"
if playing is true then
log ("playing 2")
end if
end tell
end if
end repeat
end if
So far the half solution I do is:
tell application "System Events"
if (name of application processes whose frontmost is true) = {"VLC"} then return
end tell
So I check is it frontmost. Usually if I run a movie it is frontmost. I would prefer the "is playing" variation but... ok, what can I do.
I think I'm understanding the nature of your query more now. I was previously a little confused about what your objective was, but now I'm gathering it's simply to determine whether any VLC instance is playing or not. Is that correct ?
But that you do not need to know what is playing or in which window it's playing ?
And am I correct in saying that you only need to discover that a single instance out of many is playing, in which case this is sufficient to prevent some other AppleScript from executing ? Or, put another way, that other AppleScript will execute if and only if no instance of VLC is playing ?
I believe that's achievable. Although we can't use the playing property of the VLC application object, we can use properties/attributes of VLC processes/windows to determine whether or not each instance of VLC is playing.
tell application "System Events"
set _W to a reference to window 1 of (every process whose name is "VLC")
set _title to the value of attribute "AXTitle" of _W
end tell
That is literally all you need, as the AXTitle attribute returns very predictable data depending on the state of VLC:
▸ If VLC is playing and NOT fullscreen: _title evaluates to a non-empty string (specifically, it contains the name of the video file or the path to the internet stream).
▸ If VLC is NOT playing: _title evaluates to "VLC media player".
▸ If VLC is playing and IS fullscreen: _title evaluates to an empty string ("").
Therefore:
If _title = "VLC media player", then VLC is not playing; otherwise, VLC is playing.
Utilising this fact, in order for your other AppleScript to be allowed to execute, we want every _title value representing each instance of VLC to be equal to "VLC media player". If there is even one value in _title that is anything other than that, then the assertion fails and the script can terminate, or do whatever it needs to do to prevent the execution of some other script.
I chose to simply count the number of attributes returned with the name "AXTitle" and a value other than "VLC media player". The number returned is equal to the number of VLC instances currently playing:
tell application "System Events" to count ¬
(the attributes of window 1 of ¬
(every process whose name is "VLC") whose ¬
name is "AXTitle" and ¬
value is not "VLC media player")
if result is not 0 then return
I'm new to Automator.
There are many examples for simple actions.
But I couldn't find examples or documentation for launching some applications after a specific disk was mounted.
It will be very useful at work.
Has someone done this?
Ok, you want the Automator way, you get it :-D
Create a new Automator action of type Folder Action
Choose the Volumes folder of your System as input, I think you'll have to use Go to folder and type /Volumes
As first action choose Execute Applescript
Use the following script and define the first two variables to match your needs:
on run {input, parameters}
-- define the volume name and the application to start
set triggeringVolumeName to "YOUR_VOLUME_NAME"
set applicationToStart to application "Microsoft Word"
-- walk through all newly mounted volumes
repeat with aMountedVolumeAlias in input
-- get the volume name from the given alias
tell application "System Events" to set mountedVolumeName to name of aMountedVolumeAlias
-- compare the volume name with the defined trigger name
if mountedVolumeName is triggeringVolumeName then
-- launch the target application
launch applicationToStart
-- all is done stop checking
exit repeat
end if
end repeat
return input
end run
The trick is to watch for changes inside the default mount point of your system (/Volumes). Everytime something is added to the folder, the AppleScript will be executed and aliases of the newly added items (aka the new volumes) will be inside the input parameter given to the script.
We walk through the list of all item aliases and get the real name of the alias, compare it with our trigger name and in case of a match we start the application.
Have fun with Automator, Michael / Hamburg
Elaborating on ShooTerKo's answer I've written the following script that continues the Workflow if the triggeringVolumeName is found. That way the actual launch (or any other Workflow action) can be moved outside the Applescript:
Create a new Automator action of type Folder Action
Choose the Volumes folder of your system as input by clicking Other... in the Choose folder dropdown, pressing Cmd+Shift+G and typing /Volumes
As first action choose Execute Applescript
Use the following script and change YOUR_VOLUME_NAME to match your needs:
on run {input, parameters}
-- define the volume name and the application to start
set triggeringVolumeName to "YOUR_VOLUME_NAME"
-- walk through all newly mounted volumes
repeat with aMountedVolumeAlias in input
-- get the volume name from the given alias
tell application "System Events" to set mountedVolumeName to name of aMountedVolumeAlias
-- compare the volume name with the defined trigger name
if mountedVolumeName is triggeringVolumeName then
-- continue workflow
return input
end if
end repeat
-- if repeat finished without match, cancel workflow
error number -128
end run
Add other actions to the Workflow, e.g. Ask for Confirmation, Copy Finder Items or Launch Application
I know that if you input
Do
msgbox("This is a msg box")
loop
Then a msg box pops up that won't go away.
I want multiple message boxes that you ARE able to close.
How do I do this?
You want to look for non-modal dialogs. The msgbox that you pop-up here are modal, that's why they come one after the other (execution is suspended while the dialog is open).
You will find references for this on the web.
Func _NoHaltMsgBox($code=0, $title = "",$text = "" ,$timeout = 0)
Run (#AutoItExe & ' /AutoIt3ExecuteLine "MsgBox(' & $code & ', '''& $title & ''', '''& $text &''',' & $timeout & ')"')
EndFunc
WARNING: You're probably going to encounter severe lag and or crashing. I am not held responsible of any damages if you choose to continue.
You can make a batch file that opens the same VBS script many times.
Make a notepad with:
msgbox("YourTextHere")
Or if you want to loop it:
do
msgbox("YourTextHere")
loop
Replace YourTextHere with whatever you want.
Then save it as .vbs
then make another notepad:
start "MessageBox" "MessageBox.vbs"
Change "MessageBox" with the name of the message box VBS you made.
Copy and paste the same script multiple times to open it more times (Do this at your own risk, you may encounter severe lag).
Then save it as .bat
Or add the batch file itself multiple times so it can create a loop of opening batch files which can open more scripts out of them. (Do this at your own risk, you may encounter severe lag).
For example:
start "BatchFile" "Batchfile.bat"
Change "BatchFile" with the name of the Batchfile you made.
Copy and paste it multiple times to open it more times again (Do this at your own risk, you may encounter severe lag).
So far, you're okay since you did not open the .bat file. IF you try testing it, It'll open multiple instances of your .bat file and the message box, then open more instances off the new instances, then more instances off the even newer instances, and repeat enough to make your PC crash or lag.
If you don't want to use a batch file, try this:
Step 1 - the error message
Let's say you wanted a=msgbox("messageboxtext"). So, in Notepad, you would write a=msgbox("messageboxtext") and save it as a .vbs file.
Step 2 - the spammer
Infinitely
In a new Notepad document, paste this:
set shell = createobject("wscript.shell")
count = "hello world"
do until count = 1
shell.run("""C:\Users\user\Documents\error.vbs""")
loop
Replace C:\Users\user\Documents\error.vbs with the location of the file. Save it as a .vbs file.
Finitely
To open a finite number of windows, use this code:
set shell = createobject("wscript.shell")
count = 0
do until count = 5
shell.run("""C:\Users\user\Documents\error.vbs""")
loop
Replace the 5 with the number of times you would like the message to spawn. Enjoy!
You need a multiple button MsgBox, set it as a value then: if CANCEL is pressed, the process will stop.
Do
spam=MsgBox("SPAM",3)
If spam = 2 Then
WScript.Quit
End If
Loop
First make an File called "anything.vbs" replace anything with anything you want.
Then Edit it and Put in the Code
msgbox("LOL")
loop"
Replace LOL with anything you Like.
Then make a .bat File.
Put in the Code
start "LOL.bat"
loop"
Now you have a Spammer. :)
There is an screensaver that will launch scripts in OS X - which is great, but the problem I am having is that it launches multiple copies of the script. Is there a simple way to ensure that only one copy of this script is running at a time?
John Gruber wrote a post on something very similar to this a while back. Long story short, you would just wrap the entire thing in a block similar to the following:
tell application "System Events"
count (every process whose name is "BBEdit")
end tell
replacing "BBEdit" with your app name, and then launch only if the count is 0.
I am getting an AppleEvent timed out error when my Applescript is running and the screensaver turns on and locks the screen. The applescript completes the current operation and when trying to do the next Finder operation it does not proceed but waits and times out.
I cannot increase the time-out time limit since I will not unlock the screen at all. Is there a way to ignore waiting for the screen unlock or some other solution to this?
Thanks in advance.
The best answer I have received (from macscripter.net) is to use shell commands instead of Finder commands to avoid this timeout.
I don't know how you could bypass the locked screen so your code keeps working, however you might use an if statement such that when the screen saver is running then your code isn't executed. That would at least prevent the timeout error. For example suppose you wanted to run a repeat loop 10 times for some reason, and you wanted not to run some code when the screen saver is running... you could do this.
set i to 0
repeat
set screenSaverEngineIsRunning to false
tell application "System Events"
if (exists process "ScreenSaverEngine") then set screenSaverEngineIsRunning to true
end tell
if not screenSaverEngineIsRunning then
set i to i + 1
-- do some code here
end if
delay 1
if i is 10 then exit repeat
end repeat
http://www.macupdate.com/app/mac/10387/sleepwatcher
I just did a test using Python + Appscript to do my scripting rather than Applescript and it continued to run without trouble on my system when either the user was suspended (i.e. going to the login window but with the user still logged in) or if the screen save was running. It was a simple script but presumably demonstrates what you needed to do.
Appscript comes with ASTranslate which translates Applescript calls into the equivalent Python + Appscript call. It doesn't handle variables but typically you can do a little cutting and pasting to figure out how to convert your script. It really goes quick and Python is a vastly superior language to script in than Applescript.
#!/usr/bin/python
import sys, os
from appscript import *
import time
def gettodos():
cs = app(u'iCal').calendars.get()
for c in cs:
print c.name()
tds = c.todos()
for t in tds:
print " ", t.summary()
def test():
for i in range(1,1000):
print
print "Run # " + str(i)
print
gettodos()
time.sleep(10)
if __name__ == '__main__':
test()
# change to 0 for success, 1 for (partial) failure
sys.exit(0)
I cannot reproduce your problem. I tried the following script and it worked fine even when the screensaver was running.
delay 10
tell application "Finder"
name of startup disk
end tell
delay 5
tell application "Finder"
contents of startup disk
end tell
The problem must depend on the specific commands your script is executing. What are they?