The solution is that you don't do it this way. If you have a CLI app that needs to post a sidebar notification to the user, and when the user clicks it, it opens a GUI companion application, then there are two ways to handle this:
• Make your GUI application scriptable so that it can receive an AppleScript message from your CLI app and act upon it (like send a sidebar notification). This is explained here. This is the most elegant technique.
• Or, you can follow the following example to make a GUI-less Cocoa application that acts as an intermediary between the CLI app and the GUI companion application.
GUI-less Cocoa application intermediary technique
1. Create what's called a GUI-less Cocoa application that will act as an intermediary between your CLI app and the GUI application. This eliminates the ugly terminal window from opening if you had created a CLI app. Steps:
a. Create a new default Cocoa application.
b. Remove NSMainNibFile
entry out of the Info.plist.
c. Remove the XIB file and the default AppDelegate stuff (.m, .h).
d. Comment out the call to NSApplicationMain in your main.m in the main() function.
e. Add the LSUIElement key to your Info.plist and set it to YES.
2. Set an icon for this GUI-less application by copying the AppIcon.icns file from your compiled GUI application into this GUI-less application in the same directory where the main.m file is located. Then, in your Info.plist of your GUI-less application, set CFBundleIconFile to simply AppIcon. Then, do a Clean on your project so that it will use this new icon. Note -- XCode may act strange where it won't show the icon properly, but when you view it in Finder it will be fine.
3. Set your main.m of the GUI-less Cocoa application to this:
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
NSString *sTitle = @"";
NSString *sSubTitle = @"";
NSString *sText = @"";
try {
sTitle = @(argv[1]);
sSubTitle = @(argv[2]);
sText = @(argv[3]);
} catch (...) {
}
if ([sTitle isEqualToString:@""]) {
NSString *script = @"tell app \"";
// change me to your real GUI application path
script = [script stringByAppendingString:@"/Applications/Example.app"];
script = [script stringByAppendingString:@"\" to activate"];
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:script];
[appleScript executeAndReturnError:nil];
exit(0);
}
NSUserNotification *n = [[NSUserNotification alloc] init];
n.title = sTitle;
if (![sSubTitle isEqualToString:@""]) {
n.subtitle = sSubTitle;
}
n.informativeText = sText;
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
return 0;
}
4. Compile this application and stick this app folder inside your /Applications/Example.app/Contents/Resources (change that of course) folder.
5. Now you can use the following code from your CLI app to send the notification and will use the icon used in your GUI application, which makes is very pleasant. When the user clicks the notification, it will open your GUI application instead of the GUI-less application. (Actually, when you click the sidebar notification, it opens the GUI-less application, but that's not visible. The GUI-less application sees no parameters are passed to it, so it doesn't show another notification. Instead, it knows to launch your GUI application via AppleScript.)
#include <string>
std::string sTitle = "Sample Title";
std::string sSubTitle = "sample subtitle";
std::string sText = "some text";
std::string sCmd = "open -a \"";
// change me to the path of your GUI application
sCmd += "/Applications/Example.app";
// change notify.app to the name of your GUI-less application
sCmd += "/Contents/Resources/notify.app";
sCmd += "\" --args ";
sCmd += "\"" + sTitle + "\" ";
sCmd += "\"" + sSubTitle + "\" ";
sCmd += "\"" + sText + "\"";
system(sCmd.c_str());