Quit application Ccleaner after running

Hi,

I’m new here and a total beginner in applescript. I searched several threads, but could not really advance with my problem…

I’d like to know if it’s possible to do the following thing with an Applescript:

  1. Start application CCleaner for Mac (by Piriform.com) (*** important remark: see below!!! ***)
  2. Start CCleaner’s cleaning process
  3. When the Cleaning process is done, quit CCleaner

I’ve been able to make a script for the first two steps - here’s my code for that:

tell application "CCleaner"
	activate
	tell application "System Events"
		click button "Run Cleaner" of window "Ccleaner" of process "CCleaner"
	end tell
end tell

So, this starts up CCleaner and presses all the buttons/menus necessary to do the cleaning.

It’s step 3 I’m having problems with. How do I get the script to determine the cleaning process itself is over? I thought about something with an idle handler, something like the following code, but I can’t seem to get it to work:

global quit_after, check_every

set quit_after to 6
set check_every to 2

display dialog "Check is performed every " & check_every & " seconds. Things will be quit after " & quit_after & " seconds of system inactivity."

on reopen
	display dialog "Check is performed every " & check_every & " seconds. Things will be quit after " & quit_after & " seconds of system inactivity."
end reopen

on idle
	set idletime to do shell script "echo $((`ioreg -c IOHIDSystem | sed -e '/HIDIdleTime/ !{ d' -e 't' -e '}' -e 's/.* = //g' -e 'q'` / 1000000000))"
	if (idletime as integer) > quit_after then
		tell application "System Events"
			if ((name of processes) contains "CCleaner") then
				tell application "CCleaner" to quit
                                quit me
			end if
		end tell
	end if
	return check_every
end idle

It works perfectly if I just Analyze my Mac with CCleaner (there are two buttons: Analyze and Run Cleaner: see the first screenshot on the link: http://www.piriform.com/mac/ccleaner), but it doesn’t work when I Run cleaner (in the first part of my script, by making the script press that button): there’s more time needed. The thing is: the amount of time needed isn’t a constant, I want the script to wait until the cleaning process is done without having to use a long delay…

Any help would welcome! Thanks in advance!

Joe D.

*** important remark ***
ABOUT CCLEANER: I don’t want to start a discussion about cleaning “your Mac” or about using third party apps to do it - I just want a solution for my problem. So, please, see it as a challenge in Applescript, and not as the 1000th discussion whether one should or should not clean his Mac… THANKS!

Model: iMac
AppleScript: 2.3
Browser: Firefox 12.0
Operating System: Mac OS X (10.6)

You may be able to use something like this. You can find how how much of the processor a process is using. I’m assuming the process will be using the processor as it’s working and when it’s finished it’s processor usage will drop. So you can monitor that in the “on idle” handler. When you see it drop for several consecutive loops then that may be a good time to quit the application.

You’ll have to do some investigating to see if this works and find the proper parameters to know when to quit, but it may help. Good luck.

set processName to "Safari"
set processProcessorUsage to word 2 of (do shell script "/bin/ps -xcro command,%cpu | grep " & quoted form of processName)

Thanks for the reply!

That’s what I was looking for. I thought about CPU usage, but I didn’t know how to check it with applescript.
So, the code puts the CPU-usage value of a specific process (in your example Safari - in my case to be set to “CCleaner”) in the variable “processProcessorUsage”, right?
And as you suggest, this needs to be done with an idle handler to be able to check every X second.

It might be ok to just check the CPU usage by itself, and then see if it’s dropped below a certain level (yet). But what if CCleaner’s CPU usage drops below that level just for once, for 0.0001 second in the midst of its cleaning task? This will make CCleaner quit while it’s not done yet. So, I’m wondering, wouldn’t it be more solid to check whether the average of the CPU usage of CCleaner drops below a certain level?

I haven’t been testing it yet, so it’s all still a theory (maybe until tonight when I get home), but using your code, I’ve come up with the following piece of code which builds up the average CPU usage of CCleaner every two seconds by making the summation of your variable “processProcessorUsage” (which is the actual “current CPU usage” of the process). If this average CPU usage drops below a level (let’s say 8%), CCleaner is told to quit. If not, the script just continues to check the average CPU usage every two seconds. (These accuracy of the values 8% and 2 seconds will have to be checked by experiment of course.)

set idleTime to 2
set processName to "CCleaner"
set averageCPUvalue to 0
set tempCPUsum to 0
set countTics to 0
set maxCPUusage to 8
on idle
set countTics to countTics + 1
set processProcessorUsage to word 2 of (do shell script "/bin/ps -xcro command,%cpu | grep " & quoted 
form  of processName)
set tempCPUsum to tempCPUsum + processProcessorUsage
set averageCPUvalue to tempCPUsum / countTics
if averageCPUvalue  < maxCPUusage
then
tell application "CCleaner"
quit
end tell
quit me
end if
return idleTime
end idle

I’d be happy to know whether all of this makes any sense at all…
Thanks again in advance!
Joe D.

PS: can’t get the layout of the script right. Hope it’s clear though…

Model: iMac (Snow Leopard)
AppleScript: 2.3
Browser: Firefox 12.0
Operating System: Mac OS X (10.7)

Ok, so, I tried with the average thing, but there were some variables that didn’t seem to be defined as I got errors about that. Weird… So, I tried your suggestion in the first place: let the CPU usage of the process go under a specific value for a specific number of times… And it works! Thanks a lot!!!
Here’s the script:


tell application "CCleaner"
	activate
	tell application "System Events"
		click button "Run Cleaner" of window "Ccleaner" of process "CCleaner"
	end tell
end tell

global idleTime, processName, averageCPUvalue, tempCPUsum, counterTics, maxCPUusage

set idleTime to 1
set processName to "CCleaner"
set counterTics to 0
set maxCPUusage to 40

on idle
	set processProcessorUsage to word 2 of (do shell script "/bin/ps -xcro command,%cpu | grep " & quoted form of processName)
	if processProcessorUsage < maxCPUusage then
		set counterTics to counterTics + 1
		if counterTics > 2 then
			tell application "CCleaner"
				quit
			end tell
			quit me
		else
			return idleTime
		end if
	else
		return idleTime
	end if
end idle

Now, the challenge goes further: I want to elaborate this script and make it quit all (other) open apps and after that, shut down the Mac. Any ideas on that?

Cheers and thanks again!
Joe D.

A couple things.

  1. I’m glad it works!
  2. You’re lucky it works. I didn’t mention this but the value returned from the shell command is text, not a number. All shell commands return text. In other words you get back, for example, “20” as text instead of 20 as a number. So when you perform your if statement it seems applescript automatically converts the text to a number and checks if it’s less than maxCPUusage. It works but you may want to make sure the text is converted to a number yourself…
set processProcessorUsage to (word 2 of (do shell script "/bin/ps -xcro command,%cpu | grep " & quoted form of processName)) as number
  1. System Events can help you with the changes you want to make. It has a “sleep” and “shut down” commands so you can tell it to do one of those. I assume if you issue “shut down” all running applications will automatically be quit during the shutdown process as normal, so you don’t have to quit them yourself. Of course there may be some unsaved file that needs to be saved first so you’d have to watch out for that. However in 10.7 that may no longer be an issue as many apps automatically save files for you. In any case be aware of this.

I hope that helps. Good luck. :smiley:

Thanks for the heads-up!

I figured as much about the word-number definition of “processProcessorUsage”. I’m lucky it works indeed! Nevertheless, I added your “as number” addition. Thanks!

As for quitting all apps and shutting down the Mac: shutting the Mac down using System events would do the trick and it would automatically quit all apps, but you rightfully mention the problem of unsaved files. Maybe it would be better practice to first (I really mean first, as in “before ANYTHING else”!) quit all apps, and THEN run the rest of my present script to startup, run and quit CCLeaner. This is my script so far with the added code to quit all apps first: (“Clean my Mac” is the name of the stay open app I save the script in)


--quit every application, except for Finder and this script
tell application "System Events" to set the visible of every process to true

set white_list to {"Finder", "Clean my Mac"}

try
	tell application "Finder"
		set process_list to the name of every process whose visible is true
	end tell
	repeat with i from 1 to (number of items in process_list)
		set this_process to item i of the process_list
		if this_process is not in white_list then
			tell application this_process
				quit
			end tell
		end if
	end repeat
on error
	tell the current application to display dialog "An error has occurred!" & return & "This script will now quit" buttons {"Quit"} default button 1 with icon 0
end try

--run CCleaner and run cleaning task
tell application "CCleaner"
	activate
	tell application "System Events"
		click button "Run Cleaner" of window "Ccleaner" of process "CCleaner"
	end tell
end tell

--quit CCleaner and this script
global idleTime, processName, counterTics, maxCPUusage

set idleTime to 1
set processName to "CCleaner"
set counterTics to 0
set maxCPUusage to 10

on idle
	set processProcessorUsage to (word 2 of (do shell script "/bin/ps -xcro command,%cpu | grep " & quoted form of processName)) as number
	if processProcessorUsage < maxCPUusage then
		set counterTics to counterTics + 1
		if counterTics > 3 then
			tell application "CCleaner"
				quit
			end tell
			quit me
		else
			return idleTime
		end if
	else
		return idleTime
	end if
end idle

I did some testing with open apps with unsaved files and all apps politely asked whether I wanted to save the file. I didn’t save some and there was one file I did save. So, it seems to work. The only thing is that CCleaner already starts running while I am still in the process of considering whether i do or don’t want to save open files in the running apps.

Now I have to find a way to have the script wait until every app (except for the Finder of course) has quit (after saving OR not saving its open file) before starting up CCleaner and do the rest.
I have something in mind already, but I need some testing…

This is fun!
Thanks again, dude, you’ve been a great help!

Cheers,
Joe D.

PS: about the saving: I’m still on Snow Leopard, so, no automatic save for me yet. I’m not sure whether I would like that by the way, but I guess I’ll grow into if/when I upgrade to 10.7. I’ll have no choice… Typical… Apple… pfff… :wink:

Here’s an idea if yours doesn’t work. This is how you can wait for an application to actually quit before proceeding. I tried this with an unsaved excel file (which doesn’t auto-save in 10.7). Notice I have a fail-safe “maxWaitTime” so we aren’t stuck forever in the repeat loop. BTW, I don’t use the auto-save stuff myself!

set theProcess to "Microsoft Excel"
set maxWaitTime to 10
set myDelay to 0.2

tell application theProcess to quit
set inTime to current date
repeat
	tell application "System Events"
		if not (exists (application process theProcess)) then
			exit repeat
		end if
	end tell
	if (current date) - inTime is greater than maxWaitTime then exit repeat
	delay myDelay
end repeat

Thanks for the suggestion, but I’m a bit puzzled: this seems to be meant for just one app being defined beforehand (set theProcess to “Microsoft Excel”), but what about all the other open apps? I can’t just repeat this piece of code for every app I have into the script, I want the script to check whether all running apps (whatever they are) besides Finder or my script (“Clean my Mac”) have quit. If so, THEN continue with CCleaner. How can this be done? Can it be done with some piece of code just before the part where I startup CCleaner? Sorry to bother you with this…
Thanks again!
Joe D.

You can probably do it this way…

set ignoreApps to {"Finder", "AppleScript Editor", "Safari"}

-- get the name of the running applications
tell application "System Events"
	set openAppNames to name of application processes whose background only is false
end tell

-- quit the running applications
repeat with aName in openAppNames
	if aName is not in ignoreApps then
		if not quitAndWaitUntilQuit(aName, 10) then
			error "The application named " & aName & " could not be quit!"
		end if
	end if
end repeat

-- do your stuff here
-- if an app doesn't quit in the repEat loop then this code will never run because of the "error"


(*=============== SUBROUTINES ===============*)
on quitAndWaitUntilQuit(appName, maxWaitTime)
	set myDelay to 0.2
	try
		tell application appName to quit
		set inTime to current date
		repeat
			set quitProperly to false
			tell application "System Events"
				if not (exists (application process appName)) then
					set quitProperly to true
					exit repeat
				end if
			end tell
			if (current date) - inTime is greater than maxWaitTime then exit repeat
			delay myDelay
		end repeat
		return quitProperly
	on error
		return false
	end try
end quitAndWaitUntilQuit

The soap continues… :smiley:

Basically, this works: the script does wait for all apps to have quit before continuing with CCleaner…
…But I said it was a soap!.. sigh… :expressionless:
:slight_smile:

There seems to be a problem for Powerpoint and Excel (yes, from Microsoft Office for Mac 2011) when I try to actually save an open file. It gets your error code that the app could not be closed after saving the file and the script hangs…

Any ideas? Does it have to do with the maxWaitTime or something?

Thanks in advance (sorry to keep bothering you with this…)
Joe D.

In the quitAndWaitUntilQuit() handler there is a try block. If an error occurs in the try block then the handler returns “false” in the “on error” section to the main part of the script. If false is returned then the error is displayed. So it seems there is an error happening in the handler. You’ll either have to figure out why it errors and fix the code, or find another solution.

This is the nature of troubleshooting. Your task is difficult because you basically want one set of code that will work will every application. All apps are different so controlling them all is difficult… especially when it comes to Microsoft apps! :o

Dude, thank you so much for replying every time!!!

I figured as much, but wanted to be sure. I came up with another solution. Not as elegant, but still good enough for my personal needs.

The total structure is one stay open app called “Clean my Mac.app” in which I activate two other apps: one app is called “quit all apps.app” (simply made an action in automator for that…using the “ask to save” function!). The other app is “run-clean-quit CCleaner.app” and is activated conditionally by a dialog box - this dialog box says something like: “Save all your open files. If you have saved them and you want CCleaner to run, press the yes button” (but for me, it’s written in Dutch, as I’m Belgian).

With the dialog box I can actually force the main script/app (“Clean my Mac.app”) to really wait before running the whole CCLeaner process (start, clean and quit), while taking the time to save all my files. And this should work with all apps. (Tested with the trouble seekers from Microsoft already and it works!)

Here’s the code for the main app “Clean my mac.app” (the only app I actually have to start): (remark: I let Finder minimize and close its windows beforehand to have a clean desktop once all is done)


--minimize and close every Finder window
tell application "System Events" to click (first button of every window of process "Finder" whose role description is "minimize button")
tell application "Finder" to close every window

--quit all apps
tell application "System Events"
	activate application "quit all apps"
end tell

--dialog box: if yes, then continue to clean, of no, just quit all scripts...
tell application "Finder"
	tell me
		activate
		display dialog "Sla alle open bestanden op vooraleer je verder gaat. Klik daarna op 'Ja' indien je verder wil gaan met CCleaner." buttons {"Ja", "Nee"} default button 1 with icon caution
	end tell
	if the button returned of the result is "Ja" then
		tell application "run-clean-quit CCleaner app"
			activate
		end tell
	end if
end tell

quit me

I don’t have any code for the “quit all apps” app as it’s done with automator.

And here’s the script for the stay open app “run-clean-quit CCleaner.app”:

--run CCleaner and run cleaning task
tell application "CCleaner"
	activate
	tell application "System Events"
		click button "Run Cleaner" of window "Ccleaner" of process "CCleaner"
	end tell
end tell

--quit CCleaner and this script
global idleTime, processName, counterTics, maxCPUusage

set idleTime to 1
set processName to "CCleaner"
set counterTics to 0
set maxCPUusage to 10

on idle
	set processProcessorUsage to (word 2 of (do shell script "/bin/ps -xcro command,%cpu | grep " & quoted form of processName)) as number
	if processProcessorUsage < maxCPUusage then
		set counterTics to counterTics + 1
		if counterTics > 3 then
			tell application "CCleaner"
				quit
			end tell
			quit me
		else
			return idleTime
		end if
	else
		return idleTime
	end if
end idle

So, yeah, I’m happy. When I start the “Clean my Mac” app, I get a dialog box (that’s always on top by the way!) that asks whether I want to continue with CCLeaner and warns me to save open files first. When I click “no” (meaning I don’t want to run CCleaner), the script quits iself. Otherwise, in the meantime, I can just save all my files (and take my time doing it). Every time, the dialog box is there on top between saving files from different apps to warn me. When I finally click “yes”, CCleaner starts, cleans and quits and the script itself quits too…

So, yeah, I’m happy! Thanks a lot dude!
Joe D.

Great. Glad to see you got something that works for you. Applescript is fun. I hope you continue learning!