AutoShut, my first program in C#






4.96/5 (20 votes)
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.
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 typeDateTime
that holds the Date and Time of Automatic Shutdown selected by the user.AutoShutTimeSpan
: a global variable of typeTimeSpan
that holds the difference betweenAutoShutDatTime
andSystem.DateTime.No
w.
Now the parts. This application have four parts:
- 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 theAutoShutDateTime
andAutoShutTimeSpan
.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 theDateTimePicker
, Today and Tomorrow; clicking on Today will set theDateTimePicker
toSystem.DateTime.Now
; clicking on Tomorrow will set theDateTimePicker
toSystem.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 andSystem.DateTime.Now
, like this: - After selecting the
DateTime
of AutoShut, the user can choose to set a reminder that reminds him of AutoShut before theAutoShutDateTime
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.
- A Count Down Clock:
- 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 toFormWindowState.Minimized
. After minimizing either by this button or by the form's button, afrmAutoShut_Resize
event will happen that'll hide the form and show a balloon tip from thenotifyIcon
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:
- About: the about box is the default about box from Visual C# items.
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:
public void update_timespan()
{
AutoShutTimeSpan = AutoShutDateTime - System.DateTime.Now;
}
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.
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.
Using the code
I will go through the code in the same order I went through the parts of the application in the Background section:
- Taking the user input:
- "Shutdown Exactly At:" Radio Button: if this radio button was selected, the value of the
dateTimePicker
will be copied toAutShutDateTime
. TheAutoShutTimeSpan
will be calculated by calling theupdate_timespan()
method I pointed out earlier. Then we check ifAutoShutTimeSpan
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 oftotalmilliseconds
ofAutoShutTimeSpan
, 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 theAutoShutTimeSpan
. 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 thanAutoShutTimeSpan
'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. - Timers.
- Timer 1
- Timer 2
- Timer 3: the Count Down Clock
- 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. - Pause and Resume Buttons:
- 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 inpausetime
, 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
andAutoShutTimeSpan
using thepausetime
,resumetime
(typeDateTime
), andpauseDuration
(typeTimeSpan
). First we, capture the time when resuming (resumetime
), calculate thepauseDuration
, by subtractingresumetime
frompausetime
. Then we add thepauseDuration
toAutoShutDateTime
, and updateAutoShutTimeSpan
by usingupdate_timespan()
I pointed out earlier. This way we have our newAutoShutDateTime
andAutoShutTimeSpan
. 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 calledreminderIntervalDifference
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.
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
).
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:
I used three timers in the application:
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:
if the user responds with OK, the message will disappear and the computer will shutdown immediately using the
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.
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
System.Media;
class, after that you can make a SounderPlayer
variable with the path of the sound you want to play, then play it.
SoundPlayer sound1 = new SoundPlayer(@"C:\Windows\Media\notify.wav");
sound1.Play();
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:
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:
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.
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.