Вопрос

We are trying to setup a SysTray application which can be activated from elsewhere. To be more specific the activation will come from a third party app which we cannot modify but allows us to activate our own app via its path (plus a parameter/argument).

When it gets activated we want to put up a BalloonText, there are to be no forms involved.

Therefore we have two problems to solve:

  1. Make our SysTray application single instance (since it's no good generating multiple instances).

  2. Allow this other app to activate our application with arguments

Lots of help out there to help learners create simple SysTray applications (and indeed we've done it ourselves as part of a solution to an unconnected project). However we've never tried to make it single instance before.

Lots of help out there to help learners create single instance Winforms applications (again we've done this as part of other projects) but always simple applications with conventional forms (not SysTray). We use the VisualBasic WindowsFormsApplicationBase method.

Can't seem to combine these two approaches into a single solution.

Update:
Hans answer below nails it (and especially his comment):

This is already taken care of with a NotifyIcon, drop it on the form. And the "Make single instance application" checkbox. And the StartupNextInstance event. You'll need to stop assuming there's anything special about this

Это было полезно?

Решение

Everything becomes trivial when you actually do use a form. It is simple to put your app together with the designer, simple to get your app to terminate, simple to avoid a ghost icon in the tray, simple to create a context menu, simple to add popups if you ever need them.

The only un-simple thing is getting the form to not display. Paste this code in the form's class:

Protected Overrides Sub SetVisibleCore(ByVal value As Boolean)
    If Not Me.IsHandleCreated Then
        Me.CreateHandle()
        value = False
    End If
    MyBase.SetVisibleCore(value)
End Sub

The "Exit" command in the context menu is now simply:

Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
    Me.Close()
End Sub

Другие советы

As far as your first question about checking for other instances this seems to work. I used the CodeProject example as a baseline. In your Sub Main routine you can check for other instances by using the GetProcessesByName Method of the Process class. Something like this:

Public Sub Main()
    'Turn visual styles back on
    Application.EnableVisualStyles()

    'Run the application using AppContext
    Dim p() As Process
    p = Process.GetProcessesByName("TrayApp") 'Your application name here
    If UBound(p) >= 0 Then
        End
    End If
    Application.Run(New AppContext)

End Sub

For the second question if your SysTray application is already running you might want to give this article on .Net Interprocess Communication a try. Otherwise parse the CommandLine arguments in yourSub Main as it is created.

From above article:

The XDMessaging library provides an easy-to-use, zero-configuration solution to same-box cross-AppDomain communications. It provides a simple API for sending and receiving targeted string messages across application boundaries. The library allows the use of user-defined pseudo 'channels' through which messages may be sent and received. Any application can send a message to any channel, but it must register as a listener with the channel in order to receive. In this way, developers can quickly and programmatically devise how best their applications can communicate with each other and work in harmony.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top