Jump to content

Recommended Posts

Posted (edited)

Hello,

I'm trying to create a loop for our system tray application to check if their system is backing up.

 

So far I have this

 

        Private Sub BackupCheck_Tick(sender As Object, e As EventArgs) Handles BackupCheck.Tick
       If Diagnostics.Process.GetProcessesByName("SCHOOLNAMEBackup").Count = 1 Then
           NotifyIcon1.ShowBalloonTip("5000", "SCHOOLNAME Network Portal", "System backup started.", ToolTipIcon.Info)
       ElseIf Diagnostics.Process.GetProcessesByName("SCHOOLNAMEBackup").Count = 0 Then
           NotifyIcon1.ShowBalloonTip("5000", "SCHOOLNAME Network Portal", "System backup complete.", ToolTipIcon.Info)
       End If
   End Sub
End Class

 

It's not working quite right, but the basic idea is that:

>Check every 10 seconds (the timer tick) if the process is running.

>If so, show a tooltip 'started'. (if not start again)

>When it stops show a tooltip 'stopped'.

>end if - restart loop.

 

Any ideas?

Edited by GRitchie
Posted

What isn't happening?

 

On the face of it, this code only deals with the tooltip, no other calls are made here. If your timer is running, then every 10 seconds this will run, displaying a tooltip for 5 seconds - meaning the user will have a tooltip popup every 5 seconds!

 

Is that what you want?

Posted
What isn't happening?

 

On the face of it, this code only deals with the tooltip, no other calls are made here. If your timer is running, then every 10 seconds this will run, displaying a tooltip for 5 seconds - meaning the user will have a tooltip popup every 5 seconds!

 

Is that what you want?

 

 

No it's not.

I'm moving forward slowly, I think something like THIS is more what I'm looking for:

 

Private Sub BackupCheck_Tick(sender As Object, e As EventArgs) Handles BackupCheck.Tick
       Dim BackupProc = Process.Start("C:\Backup\SCHOOLNAMEBackup.exe")


       If Diagnostics.Process.GetProcessesByName("SCHOOLNAMEBackup").Count = 1 Then
           NotifyIcon1.ShowBalloonTip("5000", "SCHOOLNAME Network Portal", "System backup started.", ToolTipIcon.Info)
           While Diagnostics.Process.GetProcessesByName("SCHOOLNAMEBackup").Count = 1
               BackupProc.WaitForExit()
           End While
       ElseIf Diagnostics.Process.GetProcessesByName("SCHOOLNAMEBackup").Count = 0 Then
           NotifyIcon1.ShowBalloonTip("5000", "SCHOOLNAME Network Portal", "System backup complete.", ToolTipIcon.Info)
       End If
   End Sub
End Class

Posted
Problem is, doing this on a timer means you're now not only bombarding your user with tooltips, you're starting the process every 10 seconds too.

 

I think you want to look at using the Process.Exited callback instead of a timer - this will get called when the process finishes running: https://msdn.microsoft.com/en-us/library/system.diagnostics.process.exited%28v=vs.110%29.aspx

 

Yes that's the problem

I want a tooltip when the application starts and a tooltip when it stops.

 

I see the process.exited may be what I want but the process does not start from within the VB application itself (it's on a scheduled task within windows)

Posted

You can actually get a pointer to an already running process, which in turn gives you a Process object you can watch for the Exited callback, should solve your problem :) - https://msdn.microsoft.com/en-us/library/z3w4xdc9%28v=vs.110%29.aspx

 

So my flow would be:

* start a timer

* when timer ticks, collect process using GetProcessByName

- no process? It isn't running, so exit.

- got the process? Stop timer, assign Exited callback to it, popup tooltip

* Exited gets called - pop up tooltip, release process, restart timer

Posted
You can actually get a pointer to an already running process, which in turn gives you a Process object you can watch for the Exited callback, should solve your problem :) - https://msdn.microsoft.com/en-us/library/z3w4xdc9%28v=vs.110%29.aspx

 

So my flow would be:

* start a timer

* when timer ticks, collect process using GetProcessByName

- no process? It isn't running, so exit.

- got the process? Stop timer, assign Exited callback to it, popup tooltip

* Exited gets called - pop up tooltip, release process, restart timer

 

I think that's exactly what I want.

Could you help with the code for this?

Posted
Sure, if you don't mind waiting until later? Once I get back home, I'll throw a sample application together for you and post up the code :)

 

That would be brilliant!

 

I won't be able to test it myself until Monday now mind, but I will be sure to reply either way.

Thanks!

Posted (edited)

I've knocked a little sample together for you, code below and project attached.

 

Ended up doing it slightly differently as under inspection, it seems by default the Exited event only triggers for processes started from VB. The principle is still the same, it's just that we now manually add the event handler to the process once we capture it.

 

One thing to note - make sure your NotifyIcon actually has an icon set, otherwise it will not display. Also, I tested using Notepad as my monitor process, change the PROCESS_NAME constant to whatever your backup process is called :)

 

Imports System.Diagnostics

Public Class Form1
   Private Const PROCESS_NAME As String = "notepad"                        ' the name of the process

   Private Const BALLOON_TIMEOUT As Integer = 5000                         ' time in millis to display balloon
   Private Const BALLOON_TITLE As String = "SCHOOLNAME Network Portal"     ' title of the balloon
   Private Const BALLOON_STARTED As String = "System backup started."      ' text to display when process starts
   Private Const BALLOON_FINISHED As String = "System backup complete."    ' text to display when process exits

   Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
       'collect matching processes
       Dim runningProcesses As Process() = Process.GetProcessesByName(PROCESS_NAME)

       ' collecting processes by name means it's possible we might get multiple matches
       ' I will assume the first match is correct, however you may want to think
       ' about how to handle the event that more than one match is found.

       ' If the process is found, display a balloon to inform the user
       ' and stop the timer as there's no longer a need to monitor for new 
       ' processes. We also add an event handler to the process's Exited
       ' event, so that we will get an interrupt when the process completes.
       If runningProcesses.Length > 0 Then
           runningProcesses(0).EnableRaisingEvents = True
           AddHandler runningProcesses(0).Exited, AddressOf p_Exited
           NotifyIcon1.ShowBalloonTip( _
               BALLOON_TIMEOUT, _
               BALLOON_TITLE, _
               BALLOON_STARTED, _
               ToolTipIcon.Info)
           Timer1.Stop()
       End If
   End Sub

   ' This event is triggered when the process we find on Timer_Tick is closed or
   ' otherwise exits for any reason. We will display a balloon to inform the user
   ' the process is complete, then restart the timer to continue monitoring
   ' for the process to be started again.
   Private Sub p_Exited(ByVal sender As Object, ByVal e As System.EventArgs)
       NotifyIcon1.ShowBalloonTip( _
           BALLOON_TIMEOUT, _
           BALLOON_TITLE, _
           BALLOON_FINISHED, _
           ToolTipIcon.Info)
       Timer1.Start()
   End Sub

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Timer1.Start()
   End Sub
End Class

 

EDIT: this is the first thing I've coded in VB.NET in about 10 years - bloody painful language! :p

Notifier.zip

Edited by LosOjos
Posted

Hello,

I've given that a shot this morning but there are some build errors.

I've adjusted names for things that don't match up etc. and this is the result:

20d3c829f1d4f48c78deb569d9645cba.png

 

The on hovers say:

Handles clause requires a WithEvents variable defined in the containing type or one of its base types.

AND

Reference to a non-shared member requires an object reference.

 

Any idea as to why this might be?

Posted

Looks like your BackupCheck object is actually called BackupTimer (going off the Tick event's name), so change BackupCheck to BackupTimer.

 

Also, check the name of your NotifyIcon, the underline suggests it's not called NotifyIcon1.

 

Looking at where the highlighted errors are, that should fix it.

Posted

It seems that the timer is called 'BackupCheck' under the properties of it, and the NotifyIcon is 'NotifyIcon1'

FYI - I'm usually sensible with naming items, with this one I just decided not to bother.

Posted (edited)
It seems that the timer is called 'BackupCheck' under the properties of it, and the NotifyIcon is 'NotifyIcon1'

FYI - I'm usually sensible with naming items, with this one I just decided not to bother.

 

I'm really not sure then - have you tried running the project I attached and if so, does that work? Which version of VS are you using?

 

EDIT: are you absolutely certain about those object names? Everything points to them being wrong... also, have you just tried running it anyway? I noticed myself that the IDE seemed to be a little slow at times, but building/running the project caused a full update, clearing any no longer existing errors.

Edited by LosOjos
Posted
Your attached file works with no problem.

I'm running VS Ultimate 2013.

 

Is the code making up the body of the form that contains the NotifyIcon and Timer?

 

If you want, I'll take a look at your project for you? If you don't want to post it here, PM me for my email address.

Posted

Turns out there appears to be a bug in the implementation of Forms.Timer, meaning once stopped, it will not restart. So here's an updated version using Sytem.Timer instead:

 

Imports System.Diagnostics
Imports System.Timers

Public Class Form1
   Private Const PROCESS_NAME As String = "notepad"                        ' the name of the process

   Private Const BALLOON_TIMEOUT As Integer = 5000                         ' time in millis to display balloon
   Private Const BALLOON_TITLE As String = "SCHOOLNAME Network Portal"     ' title of the balloon
   Private Const BALLOON_STARTED As String = "System backup started."      ' text to display when process starts
   Private Const BALLOON_FINISHED As String = "System backup complete."    ' text to display when process exits

   Private Const TIMER_INTERVAL As Integer = 10000                         ' time in milis to run each check for the process

   Private timer As New Timer()

   Private Sub timer_Elapsed(sender As Object, e As EventArgs)
       'collect matching processes
       Dim runningProcesses As Process() = Process.GetProcessesByName(PROCESS_NAME)

       ' collecting processes by name means it's possible we might get multiple matches
       ' I will assume the first match is correct, however you may want to think
       ' about how to handle the event that more than one match is found.

       ' If the process is found, display a balloon to inform the user
       ' and stop the timer as there's no longer a need to monitor for new 
       ' processes. We also add an event handler to the process's Exited
       ' event, so that we will get an interrupt when the process completes.
       If runningProcesses.Length > 0 Then
           runningProcesses(0).EnableRaisingEvents = True
           AddHandler runningProcesses(0).Exited, AddressOf p_Exited
           NotifyIcon1.ShowBalloonTip( _
               BALLOON_TIMEOUT, _
               BALLOON_TITLE, _
               BALLOON_STARTED, _
               ToolTipIcon.Info)
           timer.Stop()
       End If
   End Sub

   ' This event is triggered when the process we find on Timer_Tick is closed or
   ' otherwise exits for any reason. We will display a balloon to inform the user
   ' the process is complete, then restart the timer to continue monitoring
   ' for the process to be started again.
   Private Sub p_Exited(ByVal sender As Object, ByVal e As System.EventArgs)
       NotifyIcon1.ShowBalloonTip( _
           BALLOON_TIMEOUT, _
           BALLOON_TITLE, _
           BALLOON_FINISHED, _
           ToolTipIcon.Info)
       timer.Start()
   End Sub

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       AddHandler timer.Elapsed, AddressOf timer_Elapsed
       timer.Interval = TIMER_INTERVAL
       timer.Start()
   End Sub
End Class

Notifier.zip

  • Thanks 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...