I am writing a program (for fun as well as for practical uses) that will allow me to keep track of several projects I am working on and how long I have spent working on each.
My program has a class "Project" which has the following variables:

Private projectID As Integer        ' Project's unique identifier
    Private projectTitle As String      ' Project's title
    Private description As String       ' Project's description
    Private elapsedTime As UInteger = 0 ' Total time elapsed for the project so far
    Private active As Boolean           ' Whether or not the project is active
    Private entries As New List(Of Entry)    ' A List of all entries (start-stop intervals) for this project

When active = true , the elapsedTime should increment by 1 every second. I've thought of two ways of doing this:
1) Create a timer in the main form that checks every tick for which projects are active. If the project is active, increment its elapsedTime. However, this would mean that the count would be off by milliseconds if the user does not activate the project exactly on the tick (which is not likely). Now, I know that this error is a negligible amount of time, but since I'm a bit of a perfectionist, and just for the sake of satisfying my curiosity of how it's done, I propose method 2:
2) Add a timer to class Project so that every Project object has its own timer that it can enable and disable, thus eliminating the time inaccuracy.

Unfortunately, I can't figure out how to do this. How do I add a timer to the Project class, and how do I handle the ticks? Is this even possible? Is there a better way to accomplish this?

- Z

What you should do is have one application that tracks all of the other applications. If you only intend to run it locally then you could search off the process name "myApp.exe" as that will be reliable enough.

When the "time keeper" application starts up none of the ".exe" names will be found. When it finds the first ".exe" get the processes start time:

System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcessesByName("myapp.exe");
      DateTime started = procs[0].StartTime;

Hang on to the start time ... and when the application finally quits out then take the current time. Current Time - Process Start Time = Total running time. This will be far more accurate.

There are events for Process.Exit you may be able to subscribe to that will wait for the proc to exit to get even more accurate results.

I'm sorry, I realize I didn't clearly explain how the program works. It's not supposed to track when I use other programs. It will have a list of projects I am working on, and I will manually start and stop the timer for each project when I am working on it. I won't necessarily be working on the computer for each project, so I can't rely on programs to start/stop the timers. I'll post a screenshot later today, it might help.

The same concept applies -- you don't need a timer. Click on a button when you start working on a project and it will record the current date/time. When you stop working on it then you will press the stop button and it will do DateTime.Now.Subtract(dtStartTime) and you will have the duration in a TimeSpan

And this is why I always say I spend way too much brain power thinking hard instead of smart. Thanks for your help, sknake. That sounds like a much better solution!

Ah I remembered now why I wanted to use a Timer. I was gonna have a label for each project that served as a stopwatch to show how much time has passed. I'll just use the one Timer then, and make it check for any active projects as it ticks.

Well its the same thing.... have the timer run and do the same thing

labelProject1.Text = DateTime.Now.Substract(dtProject1).ToString();
labelProject2.Text = DateTime.Now.Substract(dtProject2).ToString();

You should never use the timer to record changes in time forward. In this case when the timer executes the DateTime.Now will be later than the last time and update the label accordingly. No need to accumulate time spent inside of the timer.

This question has already been answered. Start a new discussion instead.