I am trying to create an application that will have a tray icon only, and not appear in the taskbar. (similar to Dropbox) I need to create both Windows and Mac version of the application, so I tried using MonoMac to create the Mac front-end.
What is the best way to create a tray-only application in MonoMac?
All the resources I have found say to do one of two things:
- Add
<key>LSUIElement</key><string>1</string>to theInfo.plistfile. - Add the following code to the
FinishedLaunchingevent in theAppDelegateclass:NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Accessory;
I have tried all combinations of these two, but it seems that as soon as I try to instantiate a C# System.Timers.Timer, the icon reappears in the dock at the bottom of the screen. Am I missing something about how OSX handles background applications?
What am I doing wrong? Is there a better way to make a background application that has an upper tray icon but no bottom dock icon in OSX?
(This is very similar to this SO question, but that question was from a couple years ago and was never fully answered, so I’m hoping there might be a more complete answer out there.)
Here’s the code I have so far:
public partial class AppDelegate : NSApplicationDelegate
{
MyServiceObject currentServiceObject;
public AppDelegate () { }
public override void FinishedLaunching (NSObject notification)
{
// Construct menu that will be displayed when tray icon is clicked
var notifyMenu = new NSMenu();
var exitMenuItem = new NSMenuItem("Quit My Application",
(a,b) => { System.Environment.Exit(0); }); // Just add 'Quit' command
notifyMenu.AddItem(exitMenuItem);
// Display tray icon in upper-right-hand corner of the screen
var sItem = NSStatusBar.SystemStatusBar.CreateStatusItem(30);
sItem.Menu = notifyMenu;
sItem.Image = NSImage.FromStream(System.IO.File.OpenRead(
NSBundle.MainBundle.ResourcePath + @"/notify-icon.icns"));
sItem.HighlightMode = true;
// Remove the system tray icon from upper-right hand corner of the screen
// (works without adjusting the LSUIElement setting in Info.plist)
NSApplication.SharedApplication.ActivationPolicy =
NSApplicationActivationPolicy.Accessory;
// Start running the program -- If I comment out then no dock icon appears
currentServiceObject = new MyServiceObject();
}
}
I found the problem, and it wasn’t related to the application settings at all. Evidently, there are some operations that MacOS does not allow an ‘Agent applications’ to perform. As soon as one of those methods is called, the application is forced to appear in the dock. The code that was tripping up my application was a call to:
Removing that line, and replacing it with the following MonoMac method allowed the application to remain hidden: