How to autostart an application on Mac?
How to autostart an application on Mac?
Hi,
I created a sync tool using PB and this should get started each time a user is logging in to his MacOS. I found several articles about Creating "Launch Daemons and Agents" or "Login Items" but they seem to initiate during startup without a user logged in. But I want it to run after login.
Does anyone know how I make my program autostart with user login? And, best, closing if user logs off? Maybe by simply adding a start script to some dedicated folder?
I'm using the MacOS PackageMaker to create a PKG package. Can I do it from there or should I do it using PB code?
Kukulkan
I created a sync tool using PB and this should get started each time a user is logging in to his MacOS. I found several articles about Creating "Launch Daemons and Agents" or "Login Items" but they seem to initiate during startup without a user logged in. But I want it to run after login.
Does anyone know how I make my program autostart with user login? And, best, closing if user logs off? Maybe by simply adding a start script to some dedicated folder?
I'm using the MacOS PackageMaker to create a PKG package. Can I do it from there or should I do it using PB code?
Kukulkan
Re: How to autostart an application on Mac?
Does this help ?
https://developer.apple.com/library/mac ... Items.html
https://developer.apple.com/library/mac ... Items.html
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: How to autostart an application on Mac?
Thanks, but currently I'm playing with ~/Library/LaunchDaemons/myFile.plist for launchd usage.
I think I can create this file from my applications user context during the first start. I'll see...
I think I can create this file from my applications user context during the first start. I'll see...
Re: How to autostart an application on Mac?
I'm currently trying to solve it.
First, i created a helper application (nothing too complicated here):
I edited the plist for it like that:
And of course put it into Contents/Library/LoginItems of the main app.
The helper application launches main app correctly if i start it manually.
Then, in main app:
It returns 1 as a result, but there is no new login item in system preferences and nothing is launching when i'm logging in.
Can anyone help?
First, i created a helper application (nothing too complicated here):
Code: Select all
launchApp.s = GetPathPart(ProgramFilename()) + "../../../../../../"
SetCurrentDirectory(launchApp)
launchApp = GetCurrentDirectory()
RunProgram("open",~"-a \"" + launchApp + ~"\"","")
Code: Select all
<key>LSUIElement</key>
<true/>
<key>LSBackgroundOnly</key>
<true/>
The helper application launches main app correctly if i start it manually.
Then, in main app:
Code: Select all
ImportC "/System/Library/Frameworks/ServiceManagement.framework/ServiceManagement"
CFStringCreateWithCharacters(allocator,chars.p-unicode,numChars)
SMLoginItemSetEnabled(*identifier,enabled.b)
EndImport
Procedure CFStringCreate(s.s)
ProcedureReturn CFStringCreateWithCharacters(#Null,s,Len(s))
EndProcedure
SMLoginItemSetEnabled(CFStringCreate("bundle.id.of.helper.app"),1)
Can anyone help?
Last edited by deseven on Fri Sep 09, 2016 12:19 am, edited 1 time in total.
Re: How to autostart an application on Mac?
good question, i'd like to know how too!
could it simply be a matter of copying the main executable (or a tiny executable or script that does nothing more than execute the main one and quit) to /Library/StartUpItems ?
http://macpaw.com/how-to/remove-startup-items-in-osx
could it simply be a matter of copying the main executable (or a tiny executable or script that does nothing more than execute the main one and quit) to /Library/StartUpItems ?
http://macpaw.com/how-to/remove-startup-items-in-osx
Re: How to autostart an application on Mac?
This is just an extract and untested, but we managed it using this code:
But I remember there was a permissions problem. It does not work in some case if there are multiple users created on the mac or so...
Best,
Kukulkan
Code: Select all
Procedure GlobalLog(LogType.i, LogMessage.s)
; Just a placeholder for our extended logging
Debug LogMessage.s
EndProcedure
; run an executable and return its console output
Procedure.s runCmd(program.s, params.s, wd.s = "", lf.s = #LineBreak,
Hidden.b = #False)
Protected Compiler.i
If Hidden.b = #True
Compiler.i = RunProgram(program.s, params.s, wd.s,
#PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)
Else
Compiler.i = RunProgram(program.s, params.s, wd.s,
#PB_Program_Open|#PB_Program_Read)
EndIf
Protected Output.s = ""
If Compiler.i
While ProgramRunning(Compiler.i)
Protected LineLength.i = AvailableProgramOutput(Compiler.i)
If LineLength.i > 0
Protected *buffer = AllocateMemory(LineLength.i)
ReadProgramData(Compiler.i, *buffer, LineLength.i)
Protected Line.s = PeekS(*buffer, LineLength.i, #PB_Ascii)
FreeMemory(*buffer)
Output.s + Line.s + lf.s
EndIf
Wend
CloseProgram(Compiler.i) ; Close the connection to the program
Else
GlobalLog(#RF_LOG_CRIT, "Failed running ["+program.s+"].")
EndIf
ProcedureReturn Output.s
EndProcedure
Procedure EnableAutostart(ProgramName.s, Param1.s = "", Param2.s = "", Param3.s = "")
CompilerIf #PB_Compiler_Debugger = 1
ProcedureReturn
CompilerEndIf
; dont try this in debug mode as the ide executable should not start
Protected Path.s = GetHomeDirectory() + "Library/LaunchAgents/"
If FileSize(Path.s) <> -2
GlobalLog(#RF_LOG_INFO, "Create autostart folder [" + Path.s + "].")
CreateDirectory(Path.s)
EndIf
Path.s = Path.s + ProgramName.s + ".plist"
If FileSize(Path.s) > 0
GlobalLog(#RF_LOG_VERB, "Autostart entry allready created. Leave EnableAuostart() function. Path: [" + Path.s + "]")
ProcedureReturn
EndIf
Protected Content.s = "<?xml version=\q1.0\q encoding=\qUTF-8\q?>"+#LineBreak+
"<!DOCTYPE plist PUBLIC \q-//Apple//DTD PLIST 1.0//EN\q \qhttp://www.apple.com/DTDs/PropertyList-1.0.dtd\q>"+#LineBreak+
"<plist version=\q1.0\q>"+#LineBreak+
"<dict>"+#LineBreak+
"<key>Disabled</key>"+#LineBreak+
"<false/>"+#LineBreak+
"<key>KeepAlive</key>"+#LineBreak+
"<false/>"+#LineBreak+
"<key>Label</key>"+#LineBreak+
"<string>"+ProgramName.s+"</string>"+#LineBreak+
"<key>LimitLoadToSessionType</key>"+#LineBreak+
"<array>"+#LineBreak+
" <string>Aqua</string>"+#LineBreak+
"</array>"+#LineBreak+
"<key>ProgramArguments</key>"+#LineBreak+
"<array>"+#LineBreak+
" <string>"+ProgramFilename()+"</string>"+#LineBreak
If Param1.s <> "": Content.s + " <string>"+Param1.s+"</string>"+#LineBreak : EndIf
If Param2.s <> "": Content.s + " <string>"+Param2.s+"</string>"+#LineBreak : EndIf
If Param3.s <> "": Content.s + " <string>"+Param3.s+"</string>"+#LineBreak : EndIf
Content.s + "</array>"+#LineBreak+
"<key>RunAtLoad</key>"+#LineBreak+
"<true/>"+#LineBreak+
"<key>WorkingDirectory</key>"+#LineBreak+
"<string>"+GetPathPart(ProgramFilename())+"</string>"+#LineBreak+
"</dict>"+#LineBreak+
"</plist>"
Content.s = ReplaceString(Content.s, "\q", Chr(34))
Protected f.i = OpenFile(#PB_Any, Path.s)
If f.i <> 0
WriteString(f.i, Content.s, #PB_UTF8)
CloseFile(f.i)
GlobalLog(#RF_LOG_VERB, "Wrote autostart entry to ["+Path.s+"].")
Protected res.s = runCmd("launchctl", "load " + Chr(34) + Path.s + Chr(34), "")
GlobalLog(#RF_LOG_VERB, "launchctl result: ["+res.s+"].")
Else
GlobalLog(#RF_LOG_CRIT, "Failed writing autostart entry to ["+Path.s+"].")
EndIf
EndProcedure
Procedure DisableAutostart(ProgramName.s)
CompilerIf #PB_Compiler_Debugger = 0
Protected Path.s = GetHomeDirectory() + "Library/LaunchAgents/"
Path.s = Path.s + ProgramName.s + ".plist"
If FileSize(Path.s) < 0
ProcedureReturn
EndIf
RunProgram("launchctl", "unload " + Chr(34) + Path.s + Chr(34), "")
DeleteFile(Path.s)
CompilerEndIf
EndProcedure
Best,
Kukulkan
Re: How to autostart an application on Mac?
Thanks Kukulkan, it works!
I've arranged your code to a procedure with some small additions and moved plist out of the code to be able to edit it in a more convenient way.
tested on 10.8 and 10.11
I've arranged your code to a procedure with some small additions and moved plist out of the code to be able to edit it in a more convenient way.
Code: Select all
#loginItemPlist = ~"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
~"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +
~"<plist version=\"1.0\">\n" +
~"<dict>\n" +
~"\t<key>Label</key>\n" +
~"\t<string>{appid}</string>\n" +
~"\t<key>ProgramArguments</key>\n" +
~"\t<array>\n" +
~"\t\t<string>/usr/bin/open</string>\n" +
~"\t\t<string>{apppath}</string>\n" +
~"\t</array>\n" +
~"\t<key>RunAtLoad</key>\n" +
~"\t<true/>\n" +
~"\t<key>KeepAlive</key>\n" +
~"\t<false/>\n" +
~"\t<key>LimitLoadToSessionType</key>\n" +
~"\t<string>Aqua</string></dict>\n" +
~"</plist>"
Procedure.b enableLoginItem(bundleID.s,state.b)
Protected loginItemsPath.s = GetHomeDirectory() + "Library/LaunchAgents/"
Protected loginItemPath.s = loginItemsPath + bundleID + ".plist"
Protected bundlePathPtr = CocoaMessage(0,CocoaMessage(0,CocoaMessage(0,0,"NSBundle mainBundle"),"bundlePath"),"UTF8String")
If bundlePathPtr
Protected bundlePath.s = PeekS(bundlePathPtr,-1,#PB_UTF8)
Else
ProcedureReturn #False
EndIf
If state
If FileSize(loginItemsPath) <> -2
If Not CreateDirectory(loginItemsPath)
ProcedureReturn #False
EndIf
EndIf
Protected loginItemFile = CreateFile(#PB_Any,loginItemPath)
If IsFile(loginItemFile)
Protected loginItemPlist.s = ReplaceString(#loginItemPlist,"{appid}",bundleID)
loginItemPlist = ReplaceString(loginItemPlist,"{apppath}",bundlePath)
WriteString(loginItemFile,loginItemPlist,#PB_UTF8)
CloseFile(loginItemFile)
RunProgram("launchctl",~"load \"" + loginItemPath + ~"\"","")
Else
ProcedureReturn #False
EndIf
Else
If FileSize(loginItemPath) <> -1
RunProgram("launchctl",~"unload \"" + loginItemPath + ~"\"","")
If Not DeleteFile(loginItemPath,#PB_FileSystem_Force)
ProcedureReturn #False
EndIf
EndIf
EndIf
ProcedureReturn #True
EndProcedure
; usage: enableLoginItem("com.example.myapp",#True)
Re: How to autostart an application on Mac?
awesome! from my reading though (disclaimer: mac newbie) i would've thought /Library/StartUpItems/ would be better for general apps than /Library/LaunchAgents/ ? LaunchAgents seemed more for low-level daemons?
Re: How to autostart an application on Mac?
It isn't /Library/LaunchAgents/, it's ~/Library/LaunchAgents/ actually
I don't see StartUpItems in my user Library dir anyway.
I don't see StartUpItems in my user Library dir anyway.
Re: How to autostart an application on Mac?
on El Capitan i have:
/Library/LaunchAgents, with just com.vmware.launchd.vmware-tools-userd.plist
/Library/LaunchDaemons, with just com.vmware.launchd.tools.plist
/Library/StartupItems, which is empty
but none of those directories seem to exist in my ~/Library/ (/Users/admin/Library/)
/Library/LaunchAgents, with just com.vmware.launchd.vmware-tools-userd.plist
/Library/LaunchDaemons, with just com.vmware.launchd.tools.plist
/Library/StartupItems, which is empty
but none of those directories seem to exist in my ~/Library/ (/Users/admin/Library/)
Re: How to autostart an application on Mac?
Anyway, i think that the SMLoginItemSetEnabled() method is the most preferable way to do that. But i wasn't able to solve it yet.
-
- New User
- Posts: 1
- Joined: Thu Dec 16, 2021 9:57 am
Re: How to autostart an application on Mac?
I want to learn it as well! I am always afraid that removing these startup programs by /Library/StartUpItems all by myself may result in broken login links because I am not highly technical...
Keep going!