How do I manually create an icon in the system tray?

J

Joseph Geretz

The conventional approach is easy enough; drop a NotifyIcon onto a Form.
When the form is loaded - bingo - the icon appears in the System Tray.

I can't use this approach though. I'm writing a service. But I'd like my
service to install an icon on the System Tray so that the user can start /
stop / and otherwise control the service interactively, and without having
to go to the Services applet. How do I do this?

Thanks for your advice.

- Joseph Geretz -
 
P

Peter Duniho

The conventional approach is easy enough; drop a NotifyIcon onto a Form.
When the form is loaded - bingo - the icon appears in the System Tray.

I can't use this approach though. I'm writing a service. But I'd like my
service to install an icon on the System Tray so that the user can start
/
stop / and otherwise control the service interactively, and without
having
to go to the Services applet. How do I do this?

Hmmm...I thought that services by definition were not allowed to have UI.
That would preclude the service itself from using the system tray for a
notify icon.

I do note that the "drop a NotifyIcon onto a Form" is just a shortcut for
instantiating a NotifyIcon instance. I suppose you could try doing that
from your service. But because of the above, I wouldn't expect it to work.

If it doesn't work, as predicted, I would expect that the only solution
would be to do what you'd have to do anyway, which is to write an
independent application that communicates with the service, and which
presents the UI to the user. Including (or even limited to) a NotifyIcon,
if that's what you want.

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

Joseph,

Quite simply, you don't do this from your service. This would require
your service to have an interactive user session, which you are not
guaranteed to have.

Rather, you create a program which will be executed when a user logs in
(e.g. put a shortcut to it in the Startup directory) that will place the
icon in the tray (using NotifyIcon).

Your program would then have to use Remoting/WCF (or some other
intra-process mechanism) to communicate with the service.
 
J

Joseph Geretz

Hi Peter,
Hmmm...I thought that services by definition were not allowed to have UI.
That would preclude the service itself from using the system tray for a
notify icon.

Is this really true? I have about a dozen icons in my Tray, about half of
them represent running services (e.g. PCAnywhere, SQL Server, Bluetooth,
etc.).

Writing a service is a bit of a black art from what I can see; Since a
service won't run in the IDE it's difficult to step through the code during
the development in order to test it. What I've done is implemented an #if
DEBUG conditional compiler statement in the Program module to define two
separate Main methods. If running in Debug, the program installs an icon in
the System Tray which allows the developer to test Start / Stop, etc. In
short, all of the conditions which would be encountered when running as a
legitimate Service at production runtime. Having done this, it would be nice
if I could leverage this interactive control infrastructure for runtime, but
if not, not.

Are there any whitepapers which describe logistics and best-practices for
service development using Visual Studio 2005? I am managing, but if there
are specific recommendations and approaches which work better than others,
I'd like to read up on them.

Thanks for your advice.

- Joseph Geretz -
 
P

Peter Duniho

Is this really true? I have about a dozen icons in my Tray, about half of
them represent running services (e.g. PCAnywhere, SQL Server, Bluetooth,
etc.).

I'll reiterate: I don't really know much about writing services. :) I do
_use_ them all the time though.

That said, my understanding is that the "dozen icons in your Tray" are the
UI side of the services, not put there directly by the service process.
Services can (and usually do) start without there being a logged in user
or any GUI available. So services by themselves wouldn't be able to
present a user interface, not being able to know in advance if there is
even a way to do so.

I suspect that for each of those icons in your task tray, there is a
user-side process somewhere that talks to the service for the purpose of
controlling it. You should be able to look in the Task Manager process
list (or use SysInternals Process Explorer, which provides more detailed
information) and identify processes that are services vs. processes that
are running in your logged in user's space. It is likely that you could
terminate the user-side process, without affecting the service, but
resulting in the loss of the task tray icon (you'll have to mouse over it
first to see it disappear, as the icons aren't removed until Windows tries
and fails to actually contact the process that put it there).
Writing a service is a bit of a black art from what I can see;

Oh, I don't know about that.

Well, actually...I _literally_ don't know about that. Still, I don't see
what's so difficult about it. Perhaps I'm simply speaking from
inexperience, but I don't see why a service should be any different from
any other process, except that there's no user interface. I mean, I
realize there may be particular things a service is required to implement,
things that actually make it a service. But otherwise? I don't see what
would make it so arcane.
Since a
service won't run in the IDE it's difficult to step through the code
during
the development in order to test it.

I didn't realize that a service won't run in the IDE. Can you elaborate
on that?

In any case, I would guess that remote debugging might be useful in that
scenario. That's what I use when I'm trying to debug something that for
whatever reason doesn't work when the process is started from within the
IDE (as an example, debugging drawing code is pretty challenging without
remote debugging, since every time you step in the debugger, focus
switches from the application back to the debugger, forcing new redraw
events and invalidating existing drawn graphics).

Also, I have seen people here mention that they do essentially what you've
done, with respect to debugging. A common technique seems to be making
the service a console application for the purposes of debugging, then
removing the small console wrapper required when actually deploying the
service.
[...]
Are there any whitepapers which describe logistics and best-practices for
service development using Visual Studio 2005? I am managing, but if there
are specific recommendations and approaches which work better than
others,
I'd like to read up on them.

Hopefully someone with more experience with writing services can answer
that question. I think it's likely there are documents on MSDN for it,
but don't know off-hand where they are.

Pete
 
J

Joseph Geretz

Hi Peter,
I didn't realize that a service won't run in the IDE. Can you elaborate
on that?

Not much to elaborate. A service application simply won't execute in the IDE
which makes it difficult to work with while developing / debugging.
Therefore, the 'black art' which I referred to isn't so much in creating the
service itself; that's pretty simple. The trick (i.e. 'black art' which I
refer to) is in structuring the source code so that it can be executed when
compiled as a service, and so that it can be executed within the IDE as
well.

The service I'm developing now, implements the following 'trick' to run the
application as a Windows EXE from within the IDE (DEBUG), but to compile the
application as a service when compiling for Release.

static class Program
{
#if DEBUG
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new PDFIDebug());
}
#else
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new PDFIService() };
ServiceBase.Run(ServicesToRun);
}
#endif
}

While this works for me so far, it is admittedly unconventional and I'm
wondering whether Microsoft (or anyone else) provides guidance for service
development in Visual Studio 2005. Seeing as how VS 2005 now includes a
'mini web server' for Web applications and services, I will not be surprised
to see the next version of VS incorporate direct support for running
services within the IDE. For now though, we need to be a bit creative in
order to work within the limitations of the IDE when devleoping service
applications.

- Joseph Geretz -

Peter Duniho said:
Is this really true? I have about a dozen icons in my Tray, about half of
them represent running services (e.g. PCAnywhere, SQL Server, Bluetooth,
etc.).

I'll reiterate: I don't really know much about writing services. :) I do
_use_ them all the time though.

That said, my understanding is that the "dozen icons in your Tray" are the
UI side of the services, not put there directly by the service process.
Services can (and usually do) start without there being a logged in user
or any GUI available. So services by themselves wouldn't be able to
present a user interface, not being able to know in advance if there is
even a way to do so.

I suspect that for each of those icons in your task tray, there is a
user-side process somewhere that talks to the service for the purpose of
controlling it. You should be able to look in the Task Manager process
list (or use SysInternals Process Explorer, which provides more detailed
information) and identify processes that are services vs. processes that
are running in your logged in user's space. It is likely that you could
terminate the user-side process, without affecting the service, but
resulting in the loss of the task tray icon (you'll have to mouse over it
first to see it disappear, as the icons aren't removed until Windows tries
and fails to actually contact the process that put it there).
Writing a service is a bit of a black art from what I can see;

Oh, I don't know about that.

Well, actually...I _literally_ don't know about that. Still, I don't see
what's so difficult about it. Perhaps I'm simply speaking from
inexperience, but I don't see why a service should be any different from
any other process, except that there's no user interface. I mean, I
realize there may be particular things a service is required to implement,
things that actually make it a service. But otherwise? I don't see what
would make it so arcane.
Since a
service won't run in the IDE it's difficult to step through the code
during
the development in order to test it.

I didn't realize that a service won't run in the IDE. Can you elaborate
on that?

In any case, I would guess that remote debugging might be useful in that
scenario. That's what I use when I'm trying to debug something that for
whatever reason doesn't work when the process is started from within the
IDE (as an example, debugging drawing code is pretty challenging without
remote debugging, since every time you step in the debugger, focus
switches from the application back to the debugger, forcing new redraw
events and invalidating existing drawn graphics).

Also, I have seen people here mention that they do essentially what you've
done, with respect to debugging. A common technique seems to be making
the service a console application for the purposes of debugging, then
removing the small console wrapper required when actually deploying the
service.
[...]
Are there any whitepapers which describe logistics and best-practices for
service development using Visual Studio 2005? I am managing, but if there
are specific recommendations and approaches which work better than
others,
I'd like to read up on them.

Hopefully someone with more experience with writing services can answer
that question. I think it's likely there are documents on MSDN for it,
but don't know off-hand where they are.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top