Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

The ShutDown Alarm

0.00/5 (No votes)
13 Dec 2004 8  
This application does shutdown, restart, logoff and power off on a given computer at a given time. It works on all OS.

ShutDown Alarm

Introduction

Before going in detail about the application, let me tell you what this application will do? As the name suggests, it is used for shutdown, log off or restarting of the computer at a user defined time.

So what is its use?

Today, the world is going digitized. Every thing is running day & night, but not human body; it needs rest. Think of a situation when at night, you want to download your favorite song or favorite software, or you want to defragment your hard disk or burn a CDR, or do some time consuming work, where your sitting for it is not required, But you have to sit, waiting for the task to complete so that you can switch off your PC, as if it is left open, it will waste precious net usage, electricity, and electrical component life of your PC.

So one day, me and my friend came up with a solution: Shutdown Timer/Alarm, that will shutdown your computer at a user defined time. It provides both IN and AT option; means, for e.g., you can shutdown your computer in 2 hrs or you can shutdown your computer at 1.00 PM. Me and my friend decided to release the software with source code so that other users get benefited with it and also we can find bugs in our application.

So how am I achieving it? (What is the code behind it?)

Basic power behind this software is some Win32 APIs, that provide support for shutdown of the computer. There are two APIs to achieve it; these are:

  • ExitWindowEx
    BOOL ExitWindowsEx
    (
      UINT uFlags, // shutdown operation 
      DWORD dwReason // shutdown reason
    );

    Advantage: Works with all Operating Systems.

  • InitiateSystemShutdown
    BOOL InitiateSystemShutdown
    ( 
        LPTSTR lpMachineName, // computer name 
        LPTSTR lpMessage, // message to display 
        DWORD dwTimeout, // length of time to display 
        BOOL bForceAppsClosed, // force closed option 
        BOOL bRebootAfterShutdown // reboot option 
    );

    Disadvantage: No support for Windows 9x/ME.

To provide backward sompatibility, I have written this software using the ExitWindowEx API.

Some Code Snippets

To shutdown the computer in Windows 9x/ME is very simple. Just call the ExitWindowEx with required parameters to perform system command. I.e., this way:

ExitWindowEx(EWX_SHUTDOWN,0);

Oh, I forgot to tell you about the various flags provided to perform different tasks by ExitWindowEx. Here are the options:

  • EWX_LOGOFF: Logoff the current user.
  • EWX_RESTART: Simply restart the computer.
  • EWX_SHUTDOWN: Shut down but 'AT' style.
  • EWX_POWEROFF: Shut down but 'ATX' style.

For forcibly shutting off your computer, you can use EWX_FORCE in combination with above four flags. Now, it is not that easy to shut down your computer under Windows multi-user systems like Window 2000 and XP (built on NT technology); you have to acquire the security privilege know as SE_SHUTDOWN_NAME to provide successful shutdown action.

Here is a code snippet to achieve that:

 HANDLE hToken; // handle to process token 

 TOKEN_PRIVILEGES tkp; // pointer to token structure 

 OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken); 

 // Get the LUID for shutdown privilege. 

 LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid); 

 tkp.PrivilegeCount = 1; // one privilege to set 

  // Get shutdown privilege for this process. 
 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

 AdjustTokenPrivileges(hToken,FALSE, &tkp,(PTOKEN_PRIVILEGES) NULL, 0); 

 // Cannot test the return value of AdjustTokenPrivileges.
 
 if(GetLastError() != ERROR_SUCCESS) 
 {
        MessageBox("AdjustTokenPrivileges enable failed.");
        return;
 }

Note: if you don’t enable SE_SHUTDOWN_NAME privilege, your computer will just logoff after ExitWindowEx or InitiateSystemShutdown API is called.

About System Tray Interface

This software has system tray interface, i.e., it can be operated from system tray. If you don’t know where system tray is, here I locate that for you:

System Tray

Now you are wondering how to achieve that. It is very simple using the simple API names Shell_NotifyIcon. Here is the function declaration for Shell_NotifyIcon API.

BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA lpdata);

Here are possible value of dwMessage:

  • NIM_ADD: add icon to system tray.
  • NIM_DELETE: delete icon from system tray.
  • NIM_MODIFY: modify the system tray icon.

(For e.g., when you connect to Yahoo! chat using Yahoo! messenger, the icon becomes active. And when you logoff, the icon becomes inactive).

And for parameter two, i.e., lpData, it is a pointer to the NOTIFYICONDATA structure which is some thing like this:

typedef struct  _NOTIFYICONDATA  { 
    DWORD cbSize;
    HWND  hWnd; 
    UINT  uID; 
    UINT  uFlags; 
    UINT  uCallbackMessage;
    HICON hIcon; 
    
    #if (_WIN32_IE < 0x0500)
     TCHAR szTip[64]; 
    #else 
     TCHAR szTip[128]; 
    #endif ) 
    
    DWORD dwState;
 } NOTIFYICONDATA,*PNOTIFYICONDATA;

Here is a little information for each:

  • cbSize: this variable is created to provide compatibility with other versions of NotifyIconData.
  • hIcon: icon for the system tray.
  • hWnd: handle to window which will handle the system tray icon message.
  • szTip: show tip when mouse hovers over icon.
  • CallbackMessage: application-defined message identifier. The system uses this identifier to send notifications to the window identified in hWnd. These notifications are sent when a mouse event occurs in the bounding rectangle of the icon, or when the icon is selected or activated with the keyboard.
  • uFlag: this flag notifies the system which of the above variables are to be used or not.
  • uID: any unique ID for icon.

Now, how to use that! That’s very simple. Just fill the required details and give the proper handle of the icon to the hIcon parameter to successfully plant an icon in the system bar. Let's say you have two handles for the icon: hIconSleep, hIconWake.

Now, here I initialize the structure:

#define MY_MESSAGE WM_APP+75
 ....
 NOTIFYICONDATA m_niData; //handling the ICON at System Tray Icon
 
 m_niData.cbSize=sizeof(NOTIFYICONDATA);
 m_niData.hIcon= hIconSleep; 
 m_niData.hWnd=this->m_hWnd; 
 sprintf(m_niData.szTip,"Shut Down Alarm :My Father Software inc @ 2003");
 m_niData.uCallbackMessage=MY_MESSAGE; 
 m_niData.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
 m_niData.uID=10001; 
 ......

For adding the icon to system tray:

Shell_NotifyIcon(NIM_ADD,&m_niData);

For modifying the icon:

  //now I am planting new Icon just Like Yahoo
  // does by showing Online and Offline status
  m_niData.hIcon= hIconWake; 
  Shell_NotifyIcon(NIM_MODIFY,&m_niData);

For deleting the icon from system tray:

  Shell_NotifyIcon(NIM_DELETE,&m_niData);

Now, many of you must be wondering: when we click or right click the icon of any application on the system tray, a menu becomes visible; now how to get that menu? If you read the above source code, one member of the NotifyIcon structure helps in this case, which is:

  m_niData.uCallbackMessage=MY_MESSAGE;

That means, you have to handle MY_MESSAGE window message to handle the message by your system tray icon. Now, it's very important to note that to receive the message, it is essential to pass NIF_MESSAGE flag in m_niData.uFlags.

        .....................
        BEGIN_MESSAGE_MAP(you class, you parent class) 
            ON_MESSAGE(MY _MESSAGE,OnSystemTrayMessage) 
        END_MESSAGE_MAP() 
        ......................

Now to show popup menu or for doing some other task, here is a function that will handle that prerequisite: a menu IDR_MENU1 in your resource file.

void DlgShutDown::OnSystemBarMessage(WPARAM wParam, LPARAM lParam) 
{
 //check for window Message which come in LPARAM parameter 
 
 Switch(lParam)
 { 
    case WM_LBUTTONDOWN: 
            this->ShowWindow(SW_RESTORE); 
            bMiniShow=FALSE;
            break; 

    case WM_RBUTTONDOWN: 
        {
            //Now we are showing the menu on Right Click

            CMenu mnu; //load the Menu from resource
            mnu.LoadMenu(IDR_MENU1);
            CMenu *PopUpMenu; //get the popup menu form the Menu 

            PopUpMenu=mnu.GetSubMenu(0);
            CPoint pt; //get the current cursor position
            GetCursorPos(&pt); //show the popup menu

            PopUpMenu->TrackPopupMenu(TPM_RIGHTALIGN, 
                          pt.x,pt.y,this); break;
        }
  }
 }

You can handle the popup menu messages in your current dialog class.

How to Use it?

Using in ‘AT ‘way:-

Here is a graphic which shows how to use it in ‘at’ way:

Figure Showing 'AT' Way

Here are the steps:

  • Step 1: Choose 'AT' way, i.e., Alarm.
  • Step 2: Set time.
  • Step 3: Set option for logoff, restart or shutdown.
  • Step 4: Click on button Set Timer to activate the timer.

Using ‘IN’ way

Here is a graphic that shows in way:

Figure Showing 'IN' Way

Here are the steps:

  • Step 1: Choose 'IN' way, i.e., Time Out option.
  • Step 2: Set time.
  • Step 3: Set option for logoff, restart or shutdown.
  • Step 4: Click on button Set Timer to activate timer.

Update History

  • Version 1.1: Some bugs fixed. Minimize is now working without problem. Force option added.
  • Version 1.0: First release.

Special Thanks

  • My Parents
  • My friends

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here