7 Replies Latest reply: Apr 29, 2012 9:36 PM by twtwtw
HAL 8500 Level 1 Level 1 (0 points)

Hello:

I wrote an AppleScript script and saved it as an Applet that needs to run in the background whenever the system is up.

 

1/ I tried to set it as a startup item, so that it would start running as soon as the Mac is on -- however without success. I did not find out what the proper way is of doing this.

 

2/ Then I tried to set it as a login item for each user. This is not as good, but I thought it may an alternative, 'buying me some time' to figure out how to do it properly as a system startup item. Launching the app works fine, but the user cannot log off again, because the system cannot seem to quit the script. So I have to stop the process in Activity Monitor, obviously not a solution.

 

3/ Also, I would prefer the script to not show up in the Dock.

 

Any help is appreciated, especially on question #1. 

 

Thanks,

HAL


iMac, Mac OS X (10.7.3)
  • etresoft Level 7 Level 7 (26,140 points)

    An AppleScript application cannot run as a true deamon. You could write a shell script through.

     

    There may be some error handler or notification handler you could use in AppleScript to have it cleanly exist. Take a look at the AppleScript Language Guide.

  • twtwtw Level 5 Level 5 (4,900 points)

    Actually, AppleScript applications can run hidden, it just takes a bit of effort.  You need to open the script application package, edit the info.plist, and add the LSUIElement key set to true.  Once that's set, the script application will no longer appear in the app launcher or dock.

     

    If you use Property List Editor (from XCode) it may call the key "Application is agent (UIElement)", depending on your preference settings.  if you use a plain text editor, the key/value pair looks like:

     


    <key>LSUIElement</key>

    <true/>

     

    if you want this to start up for all users, create a launchd launchagent plist that launches the script application at startup and save it in /Library/LaunchAgents.  that would look like:

     

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

    <plist version="1.0">

    <dict>

              <key>RunAtLoad</key>

              <true/>

              <key>Label</key>

              <string>admin.forUsers.someScript</string>

              <key>Program</key>

              <string>/full/path/to/script application.app</string>

    </dict>

    </plist>

     

    make sure you give the launchagent file a .plist extension, and put the script you want run somewhere in the main /Library folder (rather than your user library folder) so you don't get permissions errors.

  • HAL 8500 Level 1 Level 1 (0 points)

    Hello twtwtw:

    Thank you for your excellent advice and sorry for my ridiculous late reply.

     

    Your first suggestion works smoothly, adding the "Application is agent" key to the Info.plist file via Xcode hides the app.

     

    Also, I created the launchd launchagent plist file as you suggested and put it into /Library/LaunchAgents. The file name is irrelevant, I presume. The app itself is now in a subdirectory of /Library/StartupItems, which I thought is the appropriate place.

     

    However, the app does not start, when a user logs in, instead I do have a permission problem with the following entry in Console:

     

    Apr 29 19:08:31 My-Conputer com.apple.launchd.peruser.501[114] (...[277]): posix_spawn("/Library/StartupItems/SlowFan/SlowFan.app", ...): Permission denied

    Apr 29 19:08:31 My-Computer com.apple.launchd.peruser.501[114] (...[277]): Exited with code: 1

     

    So I have 4 questions:

     

    1/ I do not understand why I am getting the permission error, because "System" has read & write access to the folder as well as on the application. What am I missing? My own user also has the same read & write permission, so if I start it myself, it works fine.

     

    2/ Just out of curiosity, do you know what is the difference between the files in "/Library/LaunchAgents" and "/Library/LaunchDaemons"?

     

    3/ In addition, what I really wanted was to launch the app, when the system starts, even if no user is logged in. Is this possible?

     

    4/ If not, how do I avoid that the app runs multiple times in each user context? I want it to run once only.

     

    As usual, any hint is appreciated!

     

    Thanks,

    HAL

  • Camelot Level 8 Level 8 (46,220 points)

    1/ I do not understand why I am getting the permission error, because "System" has read & write access to the folder as well as on the application. What am I missing? My own user also has the same read & write permission, so if I start it myself, it works fine.

     

    /Library/StartupItems is not the right place for an item managed by launchd.

    StartupItems are launched at boot, but are detatched from launchd. If you're using launchd to manage your process it should not be in /Library/StartupItems. It can be anywhere else, though.

     

    2/ Just out of curiosity, do you know what is the difference between the files in "/Library/LaunchAgents" and "/Library/LaunchDaemons"?

     

    LaunchAgents run when a user logs in.

    LaunchDaemons run when the system boots.

     

    3/ In addition, what I really wanted was to launch the app, when the system starts, even if no user is logged in. Is this possible?

     

    See #2 above.

     

    4/ If not, how do I avoid that the app runs multiple times in each user context? I want it to run once only.

     

    Given #2 above, it seems like a pointless question:)

  • twtwtw Level 5 Level 5 (4,900 points)

    To add to what Camelot said:

     

    LaunchDaemons can't have any user interaction, and shouldn't be dependent on aything that needs to run in a login context.  if your app displays dialogs or alerts or tries to talk to applications like the Finder, then you need to make it a LaunchAgent.  Basic LaunchDaemons will run once at startup (when the main launchd process is initiated); basic LaunchAgents will run once at user login (when the user-specific launchd process is initiated).

     

    you should make sure that your app is owned by root, not by a given user.  That's probably why you're getting permissions errors.  I recommend having it owned by root/wheel with 755 permissions.  It may also be necessary to change ownership on the launchd plist file.

     

    I tend to store things like this in /Applications/Utilities/; it seems like a logical place for them.

  • HAL 8500 Level 1 Level 1 (0 points)

    OK, I understand the difference between Agents and Daemons now. Thank you both.

     

    I also moved the Applet to the Applications folder and I changed all permissions to 755 and the owner to "root" (for both, the applet package and everyhing inside as well as the launchd plist file).

     

    I still have the permission problem.

     

    It is an Applet, not a script, does that make a difference?

     

    Could it have something to do with what is inside the Applet?

     

    Any thoughts, how to debug?

  • twtwtw Level 5 Level 5 (4,900 points)

    it's not a good idea to change things inside of an app package unles you know exactly what you're doing and have a really good reason.  changing the permissions on the app itself ought to be sufficient, and messing around with the internal permissions is more likely to get in your way than help.  just sayin'...

     

    unix does not always like calling app packages directly that way.  one solution is to change the path to the internal executable (/full/path/to/script application.app/Contents/MacOS/whatever).  in this case, though, I'd try opening it with the unix open command.  change the plist file: delete the Program key/value pair and add a ProgramArguments key as follows:

     

              <key>ProgramArguments</key>

              <array>

                                       <string>open</string>

                                       <string>-a</string>

                                       <string>/full/path/to/script_application.app</string>

              </array>