Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

AutoShut, my first program in C#

4.96/5 (22 votes)
30 Apr 2012CPOL9 min read 70.4K   3.3K  
AutoShut, never been easier

Introduction

Since I was 17, I've always used an automatic shutdown software to shutdown my PC after a certain amount of time and for different reasons. But now, after I became a senior in college, I decided to make my own application to do that simple task for me. It is a useful tool that can come handy whenever needed for anybody and anytime.

Image 1

Background 

I have used various techniques in this application that can be useful for beginners and intermediate programmers.

Before I start explaining the parts of the program, you have to know some variables' names and meanings used in the program.

  • AutoShutDateTime: a global variable of type DateTime that holds the Date and Time of Automatic Shutdown selected by the user.
  • AutoShutTimeSpan: a global variable of type TimeSpan that holds the difference between AutoShutDatTime and System.DateTime.Now.

Now the parts. This application have four parts:

  1. Selecting the AutoShut Date and/or Time. The application give the user two options to select a time to shut down:
    • Shutdown Exactly At: this option, when selected, a DateTimePicker will appear next to it, which will be used to set the AutoShutDateTime and AutoShutTimeSpan . AutoShutTimeSpan will be used to set the interval of a timer that eventually will shutdown the PC when it ticks. Also, two buttons will appear above the DateTimePicker, Today and Tomorrow; clicking on Today will set the DateTimePicker to System.DateTime.Now; clicking on Tomorrow will set the DateTimePicker to System.DateTime.Now + 1 Day. 
    • Shutdown After: this option, when selected, 4 radio buttons and combo boxes will appear next to it; Minutes, Hours, Days, and Weeks. The AutoShutDateTime will be calculated by adding the value of one of the combo boxes next to each radio button and System.DateTime.Now, like this: 
    • C#
      AutoShutDateTime = System.DateTime.Now.AddMinutes(int.Parse(cmbMinutes.Text)); 

      and so on. Then the AutoShutTimeSpan will be calculated the same way it was every time, so I figured, let me make a method that will do that every time I call it. I called it update_timespan(), and this is it's body: 

      C#
      public void update_timespan()
      { 
          AutoShutTimeSpan =  AutoShutDateTime - System.DateTime.Now;
      }
  2. After selecting the DateTime of AutoShut, the user can choose to set a reminder that reminds him of AutoShut before the AutoShutDateTime comes. 
    • Remind Me Before (Minutes): when this option is selected, a combo box will appear next to it, and another option under it (Play a sound). If this option was selected when the user clicks on AutoShut button, another timer will be created, which holds the same interval value of the first timer minus the value selected or entered in the combo box next to it.
    • Play a sound: this option is used inside the second timer tick event_handler, which shows a messageBox and weather or not to play a sound.

    Image 2

  3. A Count Down Clock:
  4. The count down clock is a label that is refreshed using a third timer called Clock every time it ticks. I will explain more about it later.

  5. The buttons. I added 6 buttons to control the program:
    • AutoShut: is the button that'll take the user input from the first section, and will act upon it. More on it later.
    • Minimize: this button will minimize the form to tray, by resetting the WindowState of the form to FormWindowState.Minimized. After minimizing either by this button or by the form's button, a frmAutoShut_Resize event will happen that'll hide the form and show a balloon tip from the notifyIcon of the application that says: "AutoShut is still running."
    • Pause/Resume: this button will pause resume all timers. More on it later.
    • Reset: this button will reset everything, and stop all timers.
    • Exit: closes the form.
    • Shutdown Now!: Will show a confirmation message, that contains two buttons, yes and cancel: 
    • Image 3

      Yes will shutdown the PC, and cancel will close the message and will call the pause button event handler, that will pause the timers if they were open.

    • About: the about box is the default about box from Visual C# items.

Using the code 

Image 4

I will go through the code in the same order I went through the parts of the application in the Background section:

  1. Taking the user input:
  2. it is a series of if and else commands, that'll determine which way the user chose to enter the AutoShutDateTime, it is under the AutoShut button event handler (btnStart).

    C#
    private void btnStart_Click(object sender, EventArgs e)
    {
        //if the button was clicked twice, timers should be stoped and reseted
        timer1.Stop();
        timer2.Stop();
    
        //Show and hide the following
        btnPause.Show();
        btnResume.Hide();
    
        //===============================================================================
        //Checking radio buttons
        if (rdShutdownExactly.Checked) //"Shutdown Exactly At:" Radion Button
        {
            AutoShutDateTime = dateTimePicker1.Value;
            update_timespan();
            //set the time span (the time between now and AutoShut time entered by the user)
    
            if (AutoShutTimeSpan.TotalMilliseconds <= 0)
            //if the time picked is in the past, show an error message and exit the eventhandler
            {
                MessageBox.Show("Invalid Time! \n" + 
                  "Please pick a time after: " + System.DateTime.Now.ToString());
                goto flag;
            }
    
            //else, set the timer to required time and start counting
            timer1.Interval = (int) AutoShutTimeSpan.TotalMilliseconds;
            timer1.Enabled = true;
            timer1.Start();
        }
        else if (rdMinutes.Checked && cmbMinutes.Text != "" && !cmbMinutes.Text.Contains('.'))
        //"Shutdown After:" and Minutes Radio Buttons
        {
            //AutoShut time is now plus minutes selected from cmbMinutes
            AutoShutDateTime = System.DateTime.Now.AddMinutes(int.Parse(cmbMinutes.Text));
            update_timespan(); //set the time span (the time between now and AutoShut time)
    
            //set the timer to required time and start counting
            timer1.Interval = 60000 * int.Parse(cmbMinutes.Text);
            timer1.Enabled = true;
            timer1.Start();
        }
        else if (rdHours.Checked && cmbHours.Text != "" && !cmbHours.Text.Contains('.'))
        //"Shutdown After:" and Hours Radio Buttons
        {
            //AutoShut time is now plus hours selected from cmbHours
            AutoShutDateTime = System.DateTime.Now.AddHours(int.Parse(cmbHours.Text));
            update_timespan(); //set the time span (the time between now and AutoShut time)
    
            //set the timer to required time and start counting
            timer1.Interval = 3600000 * int.Parse(cmbHours.Text);
            timer1.Enabled = true;
            timer1.Start();
        }
        else if (rdDays.Checked && cmbDays.Text != "" && 
                    !cmbDays.Text.Contains('.')) //"Shutdown After:" and Days Radio Buttons
        {
            //AutoShut time is now plus Days selected from cmbDays
            AutoShutDateTime = System.DateTime.Now.AddDays(int.Parse(cmbDays.Text));
            update_timespan(); //set the time span (the time between now and AutoShut time)
    
            //set the timer to required time and start counting
            timer1.Interval = 86400000 * int.Parse(cmbDays.Text);
            timer1.Enabled = true;
            timer1.Start();
        }
        else if (rdWeeks.Checked && cmbWeeks.Text != "" && !cmbWeeks.Text.Contains('.'))
        //"Shutdown After:" and Weeks Radio Buttons
        {
            //AutoShut time is now plus 7 Days per week selected from cmbWeeks
            AutoShutDateTime = System.DateTime.Now.AddDays(int.Parse(cmbWeeks.Text) * 7);
            update_timespan(); //set the time span (the time between now and AutoShut time)
    
            //set the timer to required time and start counting
            timer1.Interval = 86400000 * (7 * int.Parse(cmbWeeks.Text));
            timer1.Enabled = true;
            timer1.Start();
        }
        else //in other cases like no data where selected from comboboxes,
        // an error message will appear and exits the eventhandler
        {
            MessageBox.Show("Please Choose a valid AutoShut Time");
            goto flag;
        }
    
        //===================================================================================
        //Checking "Remind me before" CheckBox
    
        if (cbRemind.Checked)
        {
            update_timespan(); //update the time span (the time between now and AutoShut time)
    
            if (AutoShutTimeSpan.TotalSeconds <= 60)
            // if a reminder is to be set 1 minute before AutoShut,
            // don't accept it, and show an error message
                MessageBox.Show("Can not set a reminder now!");
            else if (cmbRemindMinutes.Text == "")
            //if a reminder is to be set and no value is entered
            //or choosen from cmbRemindMinutes, show an error message and exit the event handler
            {
                MessageBox.Show("Please choose or enter a value for the reminder");
                goto flag;
            }
            else if (cmbRemindMinutes.Text.Contains('.'))
            {
                MessageBox.Show("Invalid Reminder");
                goto flag;
            }
            else if (int.Parse(cmbRemindMinutes.Text) >= AutoShutTimeSpan.TotalMinutes)
            {
                MessageBox.Show("Reminder is set after AutoShut time");
                goto flag;
            }
            else //set a timer to show a message to the user reminding
            // him about the AutoShut before a given time
            {
                timer2.Enabled = true;
                timer2.Interval = timer1.Interval - (60 * 1000 * int.Parse(cmbRemindMinutes.Text));
                timer2.Start();
            }
        }
        //================================================================
        //Count Down
        //set the count down timer, and update it every 1ms
    
        Clock.Interval = 1;
        Clock.Start();
        Clock.Tick += new EventHandler(Timer_Tick);
    
        //================================================================
        //Error Detection (Escape)
        flag: ;
    }

    This code checks every radio button, if one of them is selected, it enters it's code, I'll go through each if and else in this code:

    • "Shutdown Exactly At:" Radio Button: if this radio button was selected, the value of the dateTimePicker will be copied to AutShutDateTime. The AutoShutTimeSpan will be calculated by calling the update_timespan() method I pointed out earlier. Then we check if AutoShutTimeSpan is negative or positive, if negative, an error message will show up and the code will not be completed using a flag in the last point of the code; if positive the code will continue. Lastly, it will set the timer interval to the integer value of totalmilliseconds of AutoShutTimeSpan, and start the timer. Then go to the next if, else code.
    • "Shutdown After:" Radio Button and:
      • Minutes: if this radio button was checked AND the Minutes combo box text wasn't empty AND doesn't contain a "." (which means it's not a double), enter the code: first, calculate the AutoShutDateTime by adding the parsed text from the combo box to System.DateTime.Now. Update the AutoShutTimeSpan. Set the timer's interval and start it.
      • Hours: same as Minutes code. But we add hours to AutoShutDateTime.
      • Days: same as Minutes code. But we add Days to AutoShutDateTime.
      • Weeks: same as Minutes code. But we add 7 * parsed text from weeks combo box to AutoShutDateTime days. 
    • "Else": in case of errors like no entered data, show an error message and goto flag (exit the code).
    • "Remind me before" CheckBox: first thing we update the AutoShutTimeSpan; then checks if it is less than 60 seconds: if yes, we show an error message and don't accept it. Then we check if the combo box of the reminder is empty, if yes, we show an error message, and go to flag. Then we check if the value entered is a double, if yes, we show an error message, and goto flag. Then we check if the value entered is bigger than AutoShutTimeSpan's total minutes, if yes, we show an error message, and go to flag. if all that wasn't true, we set the second timer and start it.
    • The count down clock: if everything went right, set the interval of the count down timer "Clock" to 1 (millisecond), and start it so it will tick every 1 millisecond.
  3. Timers.
  4. I used three timers in the application:

    1. Timer 1
    2. Timer 1 is the timer that will tick when the AutoShutTimeSpan reaches zero. When this timer ticks, it will stop the timer, and a message (form last_chance_to_cancel) will show up reminding the user that his computer will shutdown now, it'll last 10 seconds:

      Image 5

      if the user responds with OK, the message will disappear and the computer will shutdown immediately using the

      C#
      System.Diagnostics.Process.Start("shutdown", "/s /t 0 /f");  

      command, if he pressed on "Cancel AutoShut" before the 10 seconds finishes, the computer will not shutdown, if he didn't respond at all, the computer will shutdown when the 10 seconds finishes. I used this technique as a caution, in case the user forgot that he set an AutoShut, the application gives him an opportunity to cancel the AutoShut even if the time finishes.

    3. Timer 2
    4. Timer 2 is the timer of the reminder, when it ticks, it'll stop the timer, show a message box of how many minutes remaining, and whether to play a sound or not. Playing a sound requires that you import the

      C#
      System.Media;   

      class, after that you can make a SounderPlayer variable with the path of the sound you want to play, then play it.

      C#
      SoundPlayer sound1 = new SoundPlayer(@"C:\Windows\Media\notify.wav");
      sound1.Play();  
    5. Timer 3: the Count Down Clock
    6. Image 6

      The count down clock is just a label that is refreshed every second or millisecond depending on weather you want to show the milliseconds or not, using a timer. The idea is every time the timer ticks, you must refresh the label by the time left, as shown in the following code:

      C#
      public string GetTime()
      {
          update_timespan();
          string TimeInString = "";
          int hour = AutoShutTimeSpan.Hours + (24 * AutoShutTimeSpan.Days);
          int min = AutoShutTimeSpan.Minutes;
          int sec = AutoShutTimeSpan.Seconds;
          int miliSec = AutoShutTimeSpan.Milliseconds;
      
          if (AutoShutTimeSpan.Days >= 1)
              miliSec = 0;
                  
          TimeInString = (hour < 10) ? "0" + hour.ToString() : hour.ToString();
          TimeInString += ":" + ((min < 10) ? "0" + min.ToString() : min.ToString());
          TimeInString += ":" + ((sec < 10) ? "0" + sec.ToString() : sec.ToString());
          TimeInString += ":" + ((miliSec < 10) ? "0" + miliSec.ToString() : miliSec.ToString());
          return TimeInString;
      }
      
      public void Timer_Tick(object sender, EventArgs eArgs)
      {
          //update lbTimer Label every Tick and stop when timespan reaches 0
          if (sender == Clock && AutoShutTimeSpan.TotalSeconds > 0)
              lbTimer.Text = GetTime();
      
          //change the color of the count down to red in the last minute of counting, but keep it black other wise
          if (AutoShutTimeSpan.TotalSeconds <= 60)
              lbTimer.ForeColor = System.Drawing.Color.Red;
          else
              lbTimer.ForeColor = System.Drawing.Color.Black;
      
          //reset the counter when the timespan reaches zero or below
          if (AutoShutTimeSpan.TotalMilliseconds <= 0)
              lbTimer.Text = "00:00:00:00";
      }
      
      public void update_timespan()
      {
          //set the time span (the time between now and AutoShut time entered by the user)
          AutoShutTimeSpan =  AutoShutDateTime - System.DateTime.Now;
      }

      Using the update_timespan() method, we can determine the time left to AutoShutDateTime anytime in our program. So if we used the count down timer "Clock", we can call that method every 1 millisecond. Which means we update the countdown label every 1 millisecond by the time left. That gives us the countdown clock.

    I added some optional features and error prevention to it:

    • the color of the text will change to red when it reaches the last minute.
    • it has to stop updating the time when the AutoShutTimeSpan reaches zero or less.
    • it resets the label to it's default value when AutoShutTimeSpan's total milliseconds reaches zero or below, because it takes more than 0 ms to execute the code.
    • Milliseconds will not be shown if the the AutoShutTimeSpan is more than 24 hours. 
  5. Pause and Resume Buttons:
  6. C#
    public void btnPause_Click(object sender, EventArgs e)
    {
        //if the user wants to pause AutoSh
        if (AutoShutTimeSpan.TotalMilliseconds > 0)
        {
            //capture the time when pausing
            pausetime = System.DateTime.Now;
    
            //show and hide the following
            btnResume.Show();
            btnPause.Hide();
    
            //check if timer2 is enabled or disabled
            /*bool*/timer2WasEnabled = timer2.Enabled;
    
            //stop all timers
            Clock.Stop();
            timer1.Stop();
            timer2.Stop();
        }
    }
    
    private void btnResume_Click(object sender, EventArgs e)
    {
        //show and hide the following
        btnResume.Hide();
        btnPause.Show();
    
        //capture the time when resuming
        DateTime resumetime;
        resumetime = System.DateTime.Now;
    
        //calculate the time span of the pause, by subtracting the resume time from the pause time
        TimeSpan pauseDuration = resumetime.Subtract(pausetime);
    
        //add the pause duration to the AutoShut time (postpone AutoShut), and update the AutoShut time span
        AutoShutDateTime += pauseDuration;
        update_timespan();
    
        //postpone the timers as well
        int reminderIntervalDifference = timer1.Interval - timer2.Interval;
        timer1.Interval = (int) AutoShutTimeSpan.TotalMilliseconds; //(int)pauseDuration.TotalMilliseconds;
        if (timer2WasEnabled)
            timer2.Interval = timer1.Interval - reminderIntervalDifference;
    
        //start all timers back
        Clock.Start();
        timer1.Start();
        if (timer2WasEnabled) //start timer 2 only if it was running before pause
            timer2.Start();
    }

    Note that pausetime (type DateTime) and timer2WasEnabled (type bool) is both global variables.

    • Pause Button: the pause operation is simple, it works only if AutoShutTimeSpan milliseconds has a value greater than 0, which means you can't pause if the timers aren't running. If that's ok, first we capture the time now and store it in pausetime, then we hide the pause button, and show the resume button, then we check if Timer 2 (the reminder) is enabled or disabled and store the bool in timer2WasEnabled, then we stop all Timers.
    • Resume Button: after we pause, the resume button appears. When the user click on it, we must calculate a new AutoShutDateTime and AutoShutTimeSpan using the pausetime, resumetime (type DateTime), and
      pauseDuration 
      (type TimeSpan). First we, capture the time when resuming (resumetime), calculate the pauseDuration, by subtracting resumetime from pausetime. Then we add the pauseDuration to AutoShutDateTime, and update AutoShutTimeSpan by using update_timespan() I pointed out earlier. This way we have our new AutoShutDateTime and AutoShutTimeSpan. But before we do any changes to the interval of Timer 1, we have to know how much time was between Timer 1 and Timer 2 set the reminder correctly after that; so we define an integer called reminderIntervalDifference and calculate that time difference. After that we are free to update the intervals, first we set the interval of Timer 1, and check weather Timer 2 was enabled before we pause or not (timer2WasEnabled), if yes, we update Timer 2's interval, otherwise we don't. Finally, we start back all timers, but not Timer 2 if it wasn't running before pause. 

Points of Interest 

Because this was my first real program in C#, everything I went through while making it was a discovery for me. I liked the language, and I will try to learn and make more programs with it in the future. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)