What is the 'on quit' handler used for? - applescript

I know all of the basic handlers, i.e. on run, on open, and on reopen. But this handler, on quit, confuses me. My questions are, what is it used for and how is it triggered?

on quit is used in scripts that have been saved as a standalone application. The user can quit such a script using its menus. A quit handler runs when the user quits the script, and can put up a confirmation dialog asking if they are sure they really want to quit, or clean up any temporary files it created, etc. -- anything the script needs to do before it ends. When you have finished doing whatever it is you want to do, continue quit to actually allow the script to exit.
Often used with an on idle handler, as scripts with such a handler can stay open for long periods of time and the user may need some way to exit them.

on quit is a function that allows you to do something on quit. To trigger it, simply use quit. For example, if I wanted to say to the user "Thanks for trying this!" then I'd do this:
--lots of code, blah blah
quit
on quit
display dialog "Thanks for trying this!" buttons {"Continue"}
continue quit
end
Which would display a dialog, then it would continue quitting. But, if I wanted to cancel quit, I'd remove the continue quit line.
Hopefully this should make sense.

Related

GNU screen quit and killall processes

I've created a .screenrc config file to setup some split screen stuff for what im working on, and i've bound ctrl+d to quit it, but it only quits the screen, and leaves the actual processes running.
Heres the bind keys part of my .screenrc file atm, is there a way i can tweek it so it kills processes too?
bindkey ^D quit
It needs to quit and kill multiple split screens btw so that may add to the complexity of it.
Ultimately i'd like to bind it to Ctrl+C or Ctrl+D, either way a quick way to exit this script as its a custom script loading this custom .screenrc file.
Thanks.
Unsure if you are aware of the screen ctrl a functions
ctrl a c to create a new screen
ctrl a a or [0-9] to run through connections
ctrl a d to detach
where you can then use
screen -r -d to re-attach
and I think you need
ctrl a \
this will attempt to quit the screen session and prompt if you wish to cancel it all

Suspending a process in bash running inside console2

In other terminals I would press Ctrl+z to suspend an application, often to then issue bg to send it into background.
In console2 Ctrl+z does nothing, probably because the key combination has a different meaning in Windows. But is there a way to achieve the same effect, save for 'process &'?
(I know I should use & and it works, but sometimes I would setup shell, start an editor, begin editing, then return to the console just to find that I forgot the & and I can't use the shell. It annoys me that I then have to either open a new shell and set it up again, or quit the editor, start it with & and set it up again).
In Console2, ctrl-c is bound by default to copy (text) you have to press ctrl-shift-c to cancel job.
You could also try to remove the hotkey that is conflicting with ctrl+z.
I was having trouble using ctrl+c to cancel the execution of a script. As soon as I removed that hotkey, ctrl+c had its default restored and I was able to cancel executions properly.
This annoying issue surely is a console2 bug. You may find something about at its issue tracker.
Anyway, what ctrl+z does is send a SIGSTOP signal to current process. So, you can still send that signal from another session/tab. (If it is less annoying than stop and start with &).
To do that, you can use the kill command.
kill -s SIGSTOP pid
(pid is the process PID number)
Hope it helps.

Google SketchUp close file

The Ruby API to Google SketchUp has a function, open_file, but I can't find a close_file function. Since I have to batch process many files, I want to close each file before moving on to the next, otherwise the program will crash from memory exhaustion.
What is the best way to close SketchUp files programmatically?
I am using Mac OS X and am willing to use AppleScript functions to signal the window to close.
EDIT
I am considering a few approaches that have proven fruitless so far.
Using the appscript Ruby gem, as described in this question. The problem here is that I cannot get SketchUp to recognize my installed gems.
In a similar vein, I am trying to use osascript (a bash program that executes AppleScripts from the shell) to close the window. That is, I call out to the shell from SketchUp's Ruby console window using one of the following:
%x[osascript -e 'tell application "SketchUp" to close window 1']
%x[osascript -e 'tell application "SketchUp" to close window 1' &]
%x[osascript -e 'tell application "SketchUp" to close every window']
%x[osascript -e 'tell application "SketchUp" to close every window' &]
Whenever I try this second approach, SketchUp just freezes. However, when I execute any of these commands from an IRB or directly from the Bash prompt outside of SketchUp, I get the desired behavior: the model window closes (incidentally, the Ruby console window remains open, which is fine).
Have a master script that launches a slave script to process each model. The slave will run within the Google SketchUp program while the master waits. When the slave is finished, it signals the master, and the master closes the SketchUp file. To do this interprocess communication, I tried using drb. However, when I try to require drb within SketchUp, I get the following message:
Error: LoadError: (eval):5:in 'require': no such file to load -- drb
EDIT 2
Having a separate process continuously running that closes Google Sketchup windows using AppleScript when signaled is clumsy for a number of reasons. First, it's ugly to have to have a separate process devoted to closing Sketchup windows. Second, the only effective way of communicating with the external script is through the creation of files, which is wasteful and the disk access may be slowing things down.
However, the most severe issue is that Sketchup is slow at responding to AppleScript commands. I have a pretty computation intensive script running in Sketchup, and it seems to starve the AppleScript response, which means that the osascript times out before the windows close. Sketchup only gets around to responding to AppleScript when there is a dialogue box prompt in Sketchup that pauses the execution of my computationally intensive script.
EDIT 3
I have modified my close_file function to pause execution of the script by displaying a dialog box. This essentially yields the current thread and allows the thread that responds to AppleScript commands to execute:
def close_file()
f = '/temp/mutex.txt' # for finer control, use different mutex for each window you want closed
File.new(f, 'w').close
result = UI.messagebox "Click OK when window has closed."
end
Then the separate ruby script that closes windows via AppleScript will additionally have to click "OK" in the dialog box. AppleScript to do that is:
tell application "System Events"
tell process "SketchUp"
set frontmost to true
keystroke return
end tell
end tell
This modification is an improvement. It corrects the "most severe issue" mentioned in EDIT 2, but the other issues remain.
There is an important limitation with using an external AppleScript to force SketchUp to do something. SketchUp will not accept any user input while a menu script is running.
I found this out trying to setup an automated rendering solution. I added a menu item which opens a WebDialog to get a list of models to download from a server. It then steps through the list and uses cURL to download each model. Once downloaded it loads the model, renders it out, uploads the images using cURL again, and goes to the next model.
What I wanted was to activate the AppleScript after each model is rendered (using the "mutex" file solution shown above) and have it close the model window. Unfortunately, since the menu script is still running, SketchUp will not respond to anything the AppleScript tells it to do. Only once all of the models have been processed and the menu script exits, will the AppleScript finally run.
This would not be so bad if all of the calls to the AppleScript were queued up, but they aren't. It seems that only the last two get honored (that number may be just an accident dependent on the timing of when my calls to the AppleScript were made relative to when the menu script finished).
Because of this limitation, I was not able to use the mutex wait() function in my menu Ruby code. Since the AppleScript was not able to execute, it never created its "I'm done" mutex file, and therefore the wait() function in Ruby never got the signal that it could continue. The result was a deadlock between AppleScript and SketchUp, such that SketchUp just freezes up (well, actually it is just stuck in a really tight loop in the wait() function).
So, when approaching this problem, think of AppleScript as a cleanup tool you can call when all of your processing is done.
One solution is to have a separate process continuously running that will close Google Sketchup windows using AppleScript when signaled. The approach described here uses files to do the interprocess communication (drb did not seem to work).
First, you have to make sure Sketchup supports AppleScripting. To do this, execute the following at the command prompt (with appropriate substitutions for different Sketchup versions, etc.):
$ defaults write /Applications/Google\ SketchUp\ 8/SketchUp.app/Contents/Info NSAppleScriptEnabled -bool YES
Now, create a separate file that will close Sketchup windows. Here is my closer.rb file:
#!/usr/bin/ruby
## closer.rb ##
def wait(f)
while !File::exists?(f)
end
File.delete(f)
end
def signal(f)
File.new(f, 'w').close
end
while true
wait('~/temp/mutex.txt')
msg = %x[osascript -e 'tell application "SketchUp" to close every window']
signal('~/temp/conf.txt')
end
Run this script from the shell. It waits until the file ~/temp/mutex.txt is created. Once the file is created, it runs osascript (essentially AppleScript) to close all the windows in Sketchup, and then signals that the windows were closed by creating a ~/temp/conf.txt file.
Here is the client code (which can be placed in your Sketchup plugins) that signals the closer script:
def wait(f)
while !File::exists?(f)
end
File.delete(f)
end
def signal(f)
File.new(f, 'w').close
end
def close_file
signal('~/temp/mutex.txt')
wait('~/temp/conf.txt')
end
The close_file signals the closer script and then waits for a confirmation that the file was closed before returning. Now you can close files in Sketchup.
You can do a lot with SketchUp using applescript and/or Automator.
tell application "SketchUp"
activate
tell application "System Events"
delay 1.0 --close window, adjust delay to suit
--key code 13 using command down -- Press ⌘W or you can use
keystroke "w" using command down
end tell
end tell
I have a number of status bar items for open new, paste to console, closing, killing SU etc.
They're tiny files that trigger the SU shortcut keys, and can be used externally, from 'Ruby Console' or as part of a plugin.
I'm not sure what kind of 'batch convert' your trying to achieve, but
I used Automator to convert most of my old v5, V6, v7 files to v8 today...
100's of them,
and your probably aware, on opening you get 'alert' warning that saving will convert the file to the latest version (which is what I wanted).
It's tricky to click this "OK" programatically.
Automator on it's own is quite restricted, but you can add an applescript to the workflow and I've found that if you use it's 'record function' to demonstrate what you need to do.
You can then copy/paste that code into 'Script Editor', get rid of the 'dowithTimeout' bits, copy it back into the workflow with delays either side and let it run.
I had to play around with delays, to accommodate some larger files, but achieved >95% success. [Success being able to select all, right click, Create Icon and Preview.]
Unfortunately I then binned the workflow, but could recreate it, if you want to have a look.
success, in Ruby Console
system("osascript -e 'tell application \"suoff\"' -e 'activate' -e 'end tell'")
and this script inside an Automator.app in applications folder....
on run
-- Make sure SU is foremost, don't click on anything else either
tell application "System Events"
tell process "SketchUp"
set frontmost to true
-- gives a message if you try to select when SU's not running
delay 0.2
tell application "SketchUp" to quit saving no
-- no dialog box etc...
delay 0.1
end tell
end tell
end run
the problem is SU has an anti self destruct ruby, that mines any linked files and aborts all efforts to shut it down... from inside itself.
so you need to bury it...
this combination works on 10.5.8 with SU8.1.
if you have a look at SketchUcation [Developer] Forum, I left a call for mac/applescript testers... I've rewritten the app since then but if you PM me I'll send you an open copy of all the bits I've got working..
john
I had to convert hundreds of .skp files with a batch processing script. I faced similar issue, since every time I opened a new file it remained opened. For me it was enough to close the active_model and the file goes with it.
This was true for SketchUp 2019 Pro Mac OS X version.
model = Sketchup.active_model
model.save(filename, Sketchup::Model::VERSION_2015)
model.close
Hope it will help

Task Scheduler - Show me a message when I lock my computer

Here's what I need to happen:
When I leave the office for the day, I lock my computer. We're supposed to fill out our timecards before leaving. I always forget to do it. I want a message to be displayed when I attempt to lock my computer asking me if I've filled out my timecard.
Here's what I've done, and why it doesn't work:
I created a task under Task Scheduler with action = "Display a message" and trigger = "On workstation lock". The problem with this is the task doesn't run until the workstation is literally locked and I don't see the message until I log back in again, which is pointless.
How can I do this so immediately after I press Ctrl-Alt-Del, but before my computer actually locks the message is displayed?
Any help would be appreciated. Bonus points awarded for the following:
1) Display the message only if after say 3:00pm, as I lock my computer multiple times a day and I would get the message every time. The 3:00pm constraint would assume I'm leaving for the day and therefore, it should ask me if I've filled it out.
2) At the end of the message, display "Would you like to visit the timecard site?" and display 2 buttons, Yes and No. If I click yes, the locking of the workstation is cancelled and the timecard site opens up in my browser. If no is clicked, the workstation goes on to be locked.
Thanks.
You could pop your message up by calling MessageBox() with the MB_SERVICE_NOTIFICATION flag. That will cause the message box to be popped up on the console even if the logon screen is showing...
I doubt that this is possible. When you press CTRL+ALT+DEL Windows handles that key press and you can't get a look in.
What you could do would be to put a shortcut on you desktop that locked the computer, but only after having shown the message you so desire. I have a Lock Workstation shortcut on my desktop which is implemented with the following target:
C:\Windows\System32\rundll32.exe User32.dll,LockWorkStation
You could quite easily write your own script, or maybe even a small app. If the latter then you simply need to call the LockWorkStation function that is exported from user32.dll.
change the action to a program, run this program
msg username message
ie: msg patrick Please remember to do this.

Can I Force MATLAB to quit after user presses Control-C?

I'm running MATLAB (command line version) from a shell script, and I'd like it to preserve shell behavior where if you press Ctrl-C it exits. But instead it wants to keep control of the terminal and I (or my poor users after me) have to type quit(1) to make it quit and tell the shell it failed.
You can't intercept Ctrl-C with a try/catch block... any other ideas? Anything I could do from the shell side to intercept the keystrokes before they get to MATLAB?
onCleanup seems like an option, but then I'd have to make the whole script thing into a function (it's already a dynamically generated try/catch block thing in a Makefile). But if that's the only thing that will work, then I'll do it...
Use onCleanup:
I wanted to do the same thing but after I read this thread I used onCleanup successfully. My problem was I had a server in Matlab that when pressing CTRL+C would keep listening on the port it was started on -> second run I would get a bind error.
You can try:
stty quit ^C
but I have no matlab to test it.

Resources