How to copy a helper app to the Application Support folder?

  1. 5 weeks ago

    Vincent V

    Dec 17 Amsterdam, The Netherlands

    Because of MAS requirements, I need to copy a helper app from my app bundle to the Application Support folder, before my app can use it.
    It works in debug mode, but not when I build the app.
    What I did is to add a Build Step / Copy Files / App Parent to my Xojo project.
    When I build the app, it's then part of the application package, it sits next to the app in Contents/MacOS.
    I want to copy it to the Application Support folder during the app's first run.
    This is my code:

    dim f as FolderItem = SpecialFolder.ApplicationData
    f = f.child("MyFolder")
    f.CreateAsFolder

    dim g as FolderItem
    g = GetFolderItem("")
    g = g.Child("MyFile")
    g.CopyFileTo (SpecialFolder.ApplicationData.child("MyFolder"))

    The folder is created, but the file doesn't copy to the folder
    It doesn't seem to find the source file when in the bundle
    I've also tried this: g = g.Child("MyFile/Contents/MacOS")

    Ideas, anyone?

  2. Beatrix W

    Dec 17 Pre-Release Testers Europe (Germany)

    Don't use Copy Files and also don't use CopyFileTo. Copy Files loves to lose the files it is supposed to copy. Use the shell command "ditto" for both.

    Why would you need to run an app from the Application Support folder? Helper apps should be run from Contents/Library/Helpers.

  3. Greg O

    Dec 17 Xojo Inc

    You may not be able to copy from the macOS folder. Try putting the helper in the Resources directory instead.

  4. Vincent V

    Dec 17 Amsterdam, The Netherlands

    Thanks.

    @Greg Same problem, source file is not found. I tried g = g.Child("Contents/Resources/MyFile")
    How do I reference a file inside the Resources folder of the bundle?

    @Beatrix I can't use a shell command, it's not allowed in the MAS.

    Helper apps should be run from Contents/Library/Helpers

    There is no Contents/Library/Helpers in my bundle? Or are you referring to some sort of hidden folder on the disk?

    -image-

  5. Beatrix W

    Dec 17 Pre-Release Testers Europe (Germany)

    You can use the shell in your own IDE script. Here is my script to copy a helper into the main app:

    'copy the scheduler to app/library/loginitems
    
    dim appPath as string = currentBuildLocation + "/" + shellEncode(currentBuildAppName)
    if right(AppPath, 4) <> ".app" then appPath = appPath + ".app"
    
    'do directory for loginitems
    dim cmd as String = "/bin/mkdir -p " + appPath + "/Contents/Library/LoginItems"
    dim theOutput as string = doShellCommand(cmd)
    if theOutput <> "" then print theOutput
    
    'get path to scheduler
    dim CountSlashes as integer = CountFields(ProjectShellPath, "/")
    dim ProjectName as string = NthField(ProjectShellPath, "/", CountSlashes)
    dim ProjectPath as String = Left(ProjectShellPath, Len(ProjectShellPath) - Len(ProjectName))
    dim PathToScheduler64 as String = ProjectPath + shellEncode("Builds - max scheduler.rbp/OS X 64 bit")
    
    'copy scheduler to app for 64bit
    cmd = "usr/bin/ditto " + PathToScheduler64 + " " + appPath + "/Contents/Library/LoginItems"
    'print "cmd " + cmd
    theOutput = doShellCommand(cmd)
    if theOutput <> "" and instr(theOutput, "can't get real path") = 0 then print theOutput
    
    // Helper functions for this script
    Function shellEncode(inValue as string) as string
      Dim rvalue as string = replaceAll(inValue, " ", "\ ")
      rvalue = replaceAll(rvalue, "&", "\&")
      rvalue = replaceAll(rvalue, "-", "\-")
      rvalue = replaceAll(rvalue, "(", "\(")
      rvalue = replaceAll(rvalue, ")", "\)")
      return rvalue
    End Function

    Anything else besides "ditto" gives problems with permissions. Been there, done that: have had much fun.

    AFAIR there is a replacement (MBS???) so that you can use the shell for MAS. But honestly, you only need something like the script above.

  6. Paul S

    Dec 17 Pre-Release Testers, Xojo Pro Europe (Netherlands, Den Haag)

    @Vincent V How do I reference a file inside the Resources folder of the bundle?

    Use SpecialFolder

  7. 4 weeks ago

    Sam R

    Dec 17 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

    @Vincent V @Beatrix I can't use a shell command, it's not allowed in the MAS.

    Helper apps should be run from Contents/Library/Helpers

    You have to use NSTask. There's an implementation in my Sandbox Kit or (almost certain) there's one in the MBS plugin.

    The biggest problem with a Sandboxed helper is file access, it doesn't have the same rights to files as your main application. It can only access a few folders on the system (namely the app support folder). In order to get the helper to open files that your main application needs, you have to create a in-secure Bookmark and use IPC to send that bookmark to the helper (I only just discovered this myself this year, I've been moving the users files around for a while now).

    Technically the limitation is not MAS, its the App Sandbox; (the rules overlap, but it's important to know which one is which as I suspect one day, the App Sandbox will be enforced outside of the App Store.

    To use helpers within a Sandboxed application, they must be code signed along with the main application (App Wrapper can help with this). Once they're code signed and also Sandboxed, they cannot be called from the Terminal or Shell. Apple won't accept the app on the App Store with the helper unsigned. So it doesn't matter if you copy the helper elsewhere (and in doing so, Apple might think you're trying to be naughty).

    My honest suggestion to you is to reconsider why you need a helper application in the first place, with the App Sandbox restrictions, it makes this process quite an upheaval just to get started.

  8. Sam R

    Dec 17 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

    Okay, so I've just seen your e-mails, I'm sorry for not responding sooner.

    In your case, you're not going to be able to modify the helper, so what you'll have to do is the following.

    Include your helper application in the "Helpers" or "MacOS" folder within your application. In code you can use OWShell class, make sure you pass True to it at creation time to use NSTask underneath.

    Move the file you want to process to the application support folder (Moving is a lot quicker than copying), then process it from there. Don't forget to move it back when you're done.

    You can use "app.executableFile.parent" to get to the "MacOS" folder within your application, if you include your Helper in that folder.

  9. @Vincent Verweij — There are many folders that you can create in your application bundle and Library/Helpers is one of them (it does not exist by default).

    Also, just to make sure, have you properly typed your app extension in the path? It has to be "myProject.app/Content/MacOS"

  10. Vincent V

    Dec 19 Amsterdam, The Netherlands

    Thanks for all the help and suggestions. I'll be trying those in the coming days.

or Sign Up to reply!