Launch app with params as front process and wait?

  • Hi,

    I was working with NSTask and came across some issues. I searched on the
    internet and found that there has been a similar query but that didn't have
    any solution. The link for that is
    http://lists.apple.com/archives/cocoa-dev//2003/May/msg01468.html. Could you
    suggest any possible solution for this.

    Also, if my parent application has a non-modal dialog up, on launching
    another app, it goes behind the non-modal dialog. Please suggest some
    solution as I am stuck with it for last few days.

    Thanks,
    Gaurav Srivastava
  • On Apr 17, 2010, at 8:14 AM, Gaurav Srivastava wrote:

    > I was working with NSTask and came across some issues. I searched on the
    > internet and found that there has been a similar query but that didn't have
    > any solution. The link for that is
    > http://lists.apple.com/archives/cocoa-dev//2003/May/msg01468.html. Could you
    > suggest any possible solution for this.
    >
    > Also, if my parent application has a non-modal dialog up, on launching
    > another app, it goes behind the non-modal dialog. Please suggest some
    > solution as I am stuck with it for last few days.

    To launch a secondary application, you should use NSWorkspace or Launch Services.  That will bring it to the front, even if it's already running.  To wait until it's finished, you can use the techniques outlined in this tech note <http://developer.apple.com/mac/library/technotes/tn/tn2050.html>.

    If you need to pass information into the other application, and you control the implementation of that application, I recommend using one of:

    * -[NSWorkspace launchApplicationAtURL:options:configuration:error:] with the relevant information in the configuration parameter

    * -[NSWorkspace launchAppWithBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifier:] with an AppleEvent descriptor

    * LSOpenFromURLSpec() with an AppleEvent descriptor in the passThruParams fields of the inLaunchSpec parameter

    You can also pass information into the application through a scripting interface.

    If you don't control the implementation of the other application and the above techniques don't suffice, you can use NSTask to launch it, but it wouldn't be my first choice.  If you need to bring it to the foreground, you'd want to use NSWorkspace to monitor for when it's launched and ready, and then activate it.  You know when it is launched when you receive the NSWorkspaceDidLaunchApplicationNotification notification which matches the application that you ran.  On 10.6 and later, you get an NSRunningApplication object with that notification, and you can activate it by invoking -activateWithOptions: on it.  For 10.5 and earlier, you get a dictionary that includes a ProcessSerialNumber, and you can use SetFrontProcess with that.

    Regards,
    Ken
  • Hi Ken,

    Thanks for the prompt reply. I got a better insight into the APIs. But
    somehow I am not able to fix my problem.

    I am using following:

    NSTask* task = [NSTask launchedTaskWithLaunchPath:@"path" arguments:args];
    int pid  = [task processIdentifier];
    ProcessSerialNumber psn;
    GetProcessForPID(pid, &psn);
    SetFrontProcess(&psn);
    [task waitUntilExit];
    SetFrontProcess(&psn);

    Even on switching to NSWorkSpace doesn't seem to solve the purpose. The
    launched application does not get highlighted. Also, one more issue I am
    facing is how to send custom events from launched application to parent
    application. Thanks in advance.

    On Sat, Apr 17, 2010 at 7:13 PM, Ken Thomases <ken...> wrote:

    > On Apr 17, 2010, at 8:14 AM, Gaurav Srivastava wrote:
    >
    >> I was working with NSTask and came across some issues. I searched on the
    >> internet and found that there has been a similar query but that didn't
    > have
    >> any solution. The link for that is
    >> http://lists.apple.com/archives/cocoa-dev//2003/May/msg01468.html. Could
    > you
    >> suggest any possible solution for this.
    >>
    >> Also, if my parent application has a non-modal dialog up, on launching
    >> another app, it goes behind the non-modal dialog. Please suggest some
    >> solution as I am stuck with it for last few days.
    >
    > To launch a secondary application, you should use NSWorkspace or Launch
    > Services.  That will bring it to the front, even if it's already running.
    > To wait until it's finished, you can use the techniques outlined in this
    > tech note <http://developer.apple.com/mac/library/technotes/tn/tn2050.html
    > >.
    >
    > If you need to pass information into the other application, and you control
    > the implementation of that application, I recommend using one of:
    >
    > * -[NSWorkspace launchApplicationAtURL:options:configuration:error:] with
    > the relevant information in the configuration parameter
    >
    > * -[NSWorkspace
    > launchAppWithBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifier:]
    > with an AppleEvent descriptor
    >
    > * LSOpenFromURLSpec() with an AppleEvent descriptor in the passThruParams
    > fields of the inLaunchSpec parameter
    >
    > You can also pass information into the application through a scripting
    > interface.
    >
    >
    > If you don't control the implementation of the other application and the
    > above techniques don't suffice, you can use NSTask to launch it, but it
    > wouldn't be my first choice.  If you need to bring it to the foreground,
    > you'd want to use NSWorkspace to monitor for when it's launched and ready,
    > and then activate it.  You know when it is launched when you receive the
    > NSWorkspaceDidLaunchApplicationNotification notification which matches the
    > application that you ran.  On 10.6 and later, you get an
    > NSRunningApplication object with that notification, and you can activate it
    > by invoking -activateWithOptions: on it.  For 10.5 and earlier, you get a
    > dictionary that includes a ProcessSerialNumber, and you can use
    > SetFrontProcess with that.
    >
    > Regards,
    > Ken
    >
    >

    --
    Gaurav Srivastava
  • On Apr 17, 2010, at 10:43 AM, Gaurav Srivastava wrote:

    > NSTask* task = [NSTask launchedTaskWithLaunchPath:@"path" arguments:args];

    OK, but that’s the code you already know doesn’t work, thanks to the previous reply, right? Use LaunchServices or NSWorkspace.

    > Even on switching to NSWorkSpace doesn't seem to solve the purpose. The
    > launched application does not get highlighted.

    You’d need to show us the code you’re using for that, for us to be able to help.

    —Jens
  • On Apr 17, 2010, at 12:43 PM, Gaurav Srivastava wrote:

    > I am using following:
    >
    > NSTask* task = [NSTask launchedTaskWithLaunchPath:@"path" arguments:args];
    > int pid  = [task processIdentifier];
    > ProcessSerialNumber psn;
    > GetProcessForPID(pid, &psn);
    > SetFrontProcess(&psn);
    > [task waitUntilExit];
    > SetFrontProcess(&psn);
    >
    > Even on switching to NSWorkSpace doesn't seem to solve the purpose. The launched application does not get highlighted. Also, one more issue I am facing is how to send custom events from launched application to parent application. Thanks in advance.

    First, you have to wait for the process to have gotten to a certain point in its startup before trying to make it the front process.  It has to acquire its connection to the window server and check in.  If you try to SetFrontProcess immediately, as shown above, it probably won't work.  In fact, you may be failing to acquire the PSN.  I hope in your real code you're checking all return values, etc.  This is why I suggested that you wait for the NSWorkspace notification that the process did launch.

    Second, are you by any chance trying to launch a program which is not packaged into an application bundle but is trying to be a GUI application?  The symptoms you describe sound like it.  Another way of asking this is, does the program work normally (become frontmost, process mouse and keyboard, etc.) if launched from the Finder?

    An unbundled GUI application does not work properly without some extra work.  You should build a proper application bundle for any GUI app.  If there's some real reason that you can't bundle the application, it can call TransformProcessType() to become a proper GUI application.

    As far as sending custom events, there are a couple of approaches.  Since you seem to be sticking with NSTask, you can communicate between the processes using pipes for standard input and output.  You can use Distributed Objects.  You can use a Unix-domain socket.  You can make the parent application scriptable and have the child script it with AppleEvents.  Etc.

    Regards,
    Ken
previous month april 2010 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today