1

I am using following applescript to relaunch finder application.

osascript -e "tell application \"Finder\"" -e "delay 1" -e "try" -e "quit" -e "delay 1" -e "activate" -e "end try" -e "end tell"  

But sometimes this script is not relaunching finder application(only quiting finder application). i am not getting any error in console.
http://www.cocoabuilder.com/archive/cocoa/113654-nsapplescript-buggy.html
Can anyone please help me out?

Parag Bafna
  • 22,812
  • 8
  • 71
  • 144

2 Answers2

4

This is the wrong way to go about things if you are using Cocoa. You should always use native APIs where possible, whereas you are attempting to call a shell script that itself builds and runs an AppleScript. Your AppleScript waits for one second before attempting a relaunch, which is an arbitrary value. You should actually be waiting for Finder to quit.

Instead, you should use the NSRunningApplication class to manage this, by using Key-Value Observing to monitor the instance's terminated property, so that you can relaunch the app when it terminates:

//assume "finder" is an ivar of type NSRunningApplication
//it has to be a strong reference or it will be released before the observation method
//is called

- (void)relaunchFinder
{
    NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"];
    if([apps count])
    {
        finder = [apps objectAtIndex:0];
        [finder addObserver:self forKeyPath:@"isTerminated" options:0 context:@"QuitFinder"];
        [finder terminate];
    }

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == @"QuitFinder")
    {
        if([keyPath isEqualToString:@"isTerminated"])
        {
            [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:@"com.apple.finder" options:NSWorkspaceLaunchDefault additionalEventParamDescriptor:NULL launchIdentifier:NULL];
            [object removeObserver:self forKeyPath:@"isTerminated"];
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}
Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
4

Here's an applescript way. You cannot rely on a specific delay time as you've seen. Therefore we manually wait for the Finder to quit by checking if it's in the list of running processes. When it is no longer in the list then we know it has quit and we can activate it again.

You'll also note I put a time check in the script because of the repeat loop. Just in case something goes wrong we do not want the repeat loop to run forever. As such if it runs for more than 10 seconds we automatically exit the repeat loop.

tell application "Finder" to quit

set inTime to current date
repeat
    tell application "System Events"
        if "Finder" is not in (get name of processes) then exit repeat
    end tell
    if (current date) - inTime is greater than 10 then exit repeat
    delay 0.2
end repeat

tell application "Finder" to activate

Here's the osascript version of that code.

/usr/bin/osascript -e 'tell application "Finder" to quit' -e 'set inTime to current date' -e 'repeat' -e 'tell application "System Events"' -e 'if "Finder" is not in (get name of processes) then exit repeat' -e 'end tell' -e 'if (current date) - inTime is greater than 10 then exit repeat' -e 'delay 0.2' -e 'end repeat' -e 'tell application "Finder" to activate'
regulus6633
  • 18,848
  • 5
  • 41
  • 49
  • Delay is required after tell application "Finder" to prevent random "Connection is Invalid -609" AppleScript errors?? – Parag Bafna Apr 19 '12 at 15:21
  • In my experience the random error is produced by trying to restart the Finder too soon before it has quit. So we use system events to wait for it to quit to prevent such issues. My repeat loop has a delay anyway to prevent what you have described. I believe the theory is sound. – regulus6633 Apr 19 '12 at 15:24
  • before quit any delay is require? – Parag Bafna Apr 19 '12 at 15:29
  • And if you really wanted to be certain, you could use the approach to check if the Finder is still running too. If the Finder is still running after 5 seconds (or whatever time you deem is appropriate) then you reissue the quit command. In either case using system events to check for the Finder running makes sense. – regulus6633 Apr 19 '12 at 15:29
  • tell application "Finder" delay 1 -- this delay is important to prevent random "Connection is Invalid -609" AppleScript errors. i got this script from total finder – Parag Bafna Apr 19 '12 at 15:33
  • An easy way to code what I just described is in the time checking code. I check for 10 seconds and then "exit repeat" whereas instead you could "Tell application Finder to quit" again. – regulus6633 Apr 19 '12 at 15:34