Windows Service w/ Notify Icon. HELP!

Joined
Dec 14, 2006
Messages
8
Programming Experience
5-10
ok, start again... (2nd time writing this out cause the 1st time the site just cleared it out on me) Anyway, I have a windows service app (more like an application with no form than an actual service) that i would like to add in the ability to have a notify icon with a context menu in the system tray that is running a small logging form that i can spit information coming from the service module exe over into to track the module. double clicking or selecting from the context menu to show this logging form else it's hidden from view. Follow? I've found some examples but they're all very basic and usually start out with a form as the startup object or they're setup in C# and while i've tried to convert it over to vb doesn't seem to work. Any help, or suggestions on this, please let me know.
 
ok, i just happened to come across an article that explains that a windows service does not interact with the desktop, therefore, no ability to add a notify icon. (yes i realize that there may be still a way, but not worth it from what i read) SO! I've come to the conclusion that i need to rework the app which brings me to the redesigned question. Since i already have the module setup I'd like to run the log form first hidden in the tray and then trigger the module to run. Any basic samples of this would be great.
 
VB.NET:
[LogWindow.vb]
[SIZE=1][COLOR=#0000ff]Imports[/COLOR][/SIZE][SIZE=1] System.Drawing[/SIZE]
[SIZE=1][COLOR=#0000ff]Imports[/COLOR][/SIZE][SIZE=1] System.Windows.Forms[/SIZE]
[SIZE=1][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Class[/COLOR][/SIZE][SIZE=1] LogWindow[/SIZE]
[SIZE=1][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1]()[/SIZE]
[SIZE=1][COLOR=#008000]' This call is required by the Windows Form Designer.[/COLOR][/SIZE]
[SIZE=1]InitializeComponent()[/SIZE]
 
[SIZE=1][COLOR=#008000]' Change the text of the form[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].Text = [/SIZE][SIZE=1][COLOR=#800000]"Log Window"[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=1] applicationContext [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] LogWindowContext = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] LogWindowContext[/SIZE]
[SIZE=1]Application.Run(applicationContext)[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Class[/COLOR][/SIZE]
 
[LogWindowContext.vb]
[SIZE=1][COLOR=#0000ff]Imports[/COLOR][/SIZE][SIZE=1] System.Windows.Forms[/SIZE]
[SIZE=1][COLOR=#0000ff]Imports[/COLOR][/SIZE][SIZE=1] System.Drawing[/SIZE]
[SIZE=1][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Class[/COLOR][/SIZE][SIZE=1] LogWindowContext[/SIZE]
[SIZE=1][COLOR=#0000ff]Inherits[/COLOR][/SIZE][SIZE=1] ApplicationContext[/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1] components [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.ComponentModel.IContainer[/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]WithEvents[/COLOR][/SIZE][SIZE=1] logIcon [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.NotifyIcon[/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1] logMenu [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.ContextMenu[/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]WithEvents[/COLOR][/SIZE][SIZE=1] exitMenu [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.MenuItem[/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]WithEvents[/COLOR][/SIZE][SIZE=1] showMenu [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.MenuItem[/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]WithEvents[/COLOR][/SIZE][SIZE=1] logForm [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.Form[/SIZE]
[SIZE=1][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] LogApplicationContext()[/SIZE]
[SIZE=1]InitializeContext()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] InitializeContext()[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].components = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] System.ComponentModel.Container()[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logIcon = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.NotifyIcon([/SIZE][SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].components)[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logMenu = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.ContextMenu[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].showMenu = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.MenuItem[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].exitMenu = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.MenuItem[/SIZE]
[SIZE=1][COLOR=#008000]' Log Notify Icon[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logIcon.ContextMenu = [/SIZE][SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logMenu[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logIcon.Icon = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] Icon([/SIZE][SIZE=1][COLOR=#800000]"import_itinerary_icon.ico"[/COLOR][/SIZE][SIZE=1])[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logIcon.Text = [/SIZE][SIZE=1][COLOR=#800000]"Importing Itineraries..."[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logIcon.Visible = [/SIZE][SIZE=1][COLOR=#0000ff]True[/COLOR][/SIZE]
[SIZE=1][COLOR=#008000]' Log Notify Context Menu[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logMenu.MenuItems.AddRange([/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] MenuItem() {showMenu, exitMenu})[/SIZE]
[SIZE=1][COLOR=#008000]' showMenu Context Item[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].showMenu.Index = 0[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].showMenu.Text = [/SIZE][SIZE=1][COLOR=#800000]"&Show Log Window"[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].showMenu.DefaultItem = [/SIZE][SIZE=1][COLOR=#0000ff]True[/COLOR][/SIZE]
[SIZE=1][COLOR=#008000]' exitMenu Context Item[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].exitMenu.Index = 1[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].exitMenu.Text = [/SIZE][SIZE=1][COLOR=#800000]"E&xit"[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Protected[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Overrides[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] Dispose([/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] disposing [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Boolean[/COLOR][/SIZE][SIZE=1])[/SIZE]
[SIZE=1][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=1] disposing [/SIZE][SIZE=1][COLOR=#0000ff]AndAlso[/COLOR][/SIZE][SIZE=1] components [/SIZE][SIZE=1][COLOR=#0000ff]IsNot[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Nothing[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Then[/COLOR][/SIZE]
[SIZE=1]components.Dispose()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=1].Dispose(disposing)[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] logIcon_DoubleClick([/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] sender [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=1], [/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] e [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.EventArgs) [/SIZE][SIZE=1][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=1] logIcon.DoubleClick[/SIZE]
[SIZE=1]ShowForm()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] showMenu_Click([/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] sender [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=1], [/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] e [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.EventArgs) [/SIZE][SIZE=1][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=1] showMenu.Click[/SIZE]
[SIZE=1]ShowForm()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] exitMenu_Click([/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] sender [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=1], [/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] e [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.EventArgs) [/SIZE][SIZE=1][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=1] exitMenu.Click[/SIZE]
[SIZE=1]ExitThread()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] ShowForm()[/SIZE]
[SIZE=1][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=1] logForm [/SIZE][SIZE=1][COLOR=#0000ff]Is[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Nothing[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Then[/COLOR][/SIZE]
[SIZE=1]logForm = [/SIZE][SIZE=1][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=1] LogWindow[/SIZE]
[SIZE=1]logForm.Show()[/SIZE]
[SIZE=1][COLOR=#0000ff]Else[/COLOR][/SIZE]
[SIZE=1]logForm.Activate()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] logForm_FormClosed([/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] sender [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=1], [/SIZE][SIZE=1][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=1] e [/SIZE][SIZE=1][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=1] System.Windows.Forms.FormClosedEventArgs) [/SIZE][SIZE=1][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=1] logForm.FormClosed[/SIZE]
[SIZE=1][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=1].logForm = [/SIZE][SIZE=1][COLOR=#0000ff]Nothing[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]Protected[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Overrides[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=1] ExitThreadCore()[/SIZE]
[SIZE=1][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=1] logForm [/SIZE][SIZE=1][COLOR=#0000ff]IsNot[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Nothing[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Then[/COLOR][/SIZE]
[SIZE=1]logForm.Close()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=1].ExitThreadCore()[/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=1][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=1][COLOR=#0000ff]Class[/COLOR][/SIZE]
Right now this is the code that i've converted to VB from a working C# application. However, it seems to hang on the application.run(). The idea behind it is to start the form hidden and just load the icon into the tray. then show the form only when the tray icon is double clicked or selected in the context menu. since this was brought over from a C# app i'm sure things run a bit differently in vb.
 
The correct way for Windows Service + UI is to separate the service and the UI in different applications, and use regular IPC methods for communication between them. IPC is short for Inter-Process Communication and can be through remoting or sockets or use of filesystem and poll/watch to read saved messages, registry etc. With the ServiceController class used for basic control/interaction with windows services there is also the option of sending an integer command to the service (ExecuteCommand method) which can respond by doing appropriate action.

To use a NotifyIcon the UI app must be a windows forms app, the notifyicon is attached to this window handle. For startup you can set the forms WindowState=Minimized and ShowInTaskBar=False (and notifyicon visible of course). For example in theNotifyIcon.MouseDoubleClick event handler you can set the forms WindowState=Normal and ShowInTaskBar=True.
 
k i'm thinking now that the best way is just to recompile the module as part of the windows.forms rather than it's own windows service. i think that may be an easier path to allow the communication between the module and the log window. any info on running a module from a form that i may need to know?

second question is, i've started setting up the form and i've got it to start up hidden and such. the problem is that i'm getting an inner exception when trying to tell it the icon to display for the tray. i'm using the icon that is part of the project, but it's still giving me an error.

nIcon.Icon = New Icon("import_itinerary_icon.ico")

it's telling me the file cannot be found, and it's looking in the debug dir within the project.
 
You can actually make the service interact with the desktop if you go into the services admin. menu, find your service an, set logon to system and check the "Allow service to interact with desktop" checkbox. Depending on what you're doing this might be the trick ya need.

I have a small windows form which all it does is update a database at the same time every day via scheduled task. There is no form, just a module with a programmatically created notification icon. The app. also updates the tooltip of the notification icon to reflect where in the update it is at. Below is a snippet of what I used to create the notification icon. There may be better ways to do it, but this worked for me:

VB.NET:
    Public noticon As New NotifyIcon
    Public icon1 As New Icon(".\ndmanager.ico")
    Public ContextMenu1 As New ContextMenu
    Public MenuItem1 As New MenuItem


    sub main()
            noticon.Visible = True
            noticon.Icon = icon1
            noticon.ContextMenu = ContextMenu1

            ContextMenu1.MenuItems.Add(MenuItem1)

            AddHandler MenuItem1.Click, AddressOf menuitem1_Click
    End sub

    Public Sub menuitem1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
           'place code here to execute whem menuitem1 is clicked           
    End Sub
 
Back
Top