Friday, November 12, 2010

Tip: Set/Remove program to run at System Startup

In this post, I'm providing helper methods to set/remove your non-service programs be automatically launched when Windows boots.

How to use:
To set your program to run every time the systems startup
ChoApplication.RunAtSystemStartup();
To set your application to run once during the systems startup
ChoApplication.RunOnceAtSystemStartup();

To remove your program from running everytime systems startup
ChoApplication.RunAtSystemStartup(true);
To remove your application from running once during the systems startup
ChoApplication.RunOnceAtSystemStartup(true);

Below is the implementation of the helper methods that we talked about. Feel free to use them. As usual, please drop your comments.

public static class ChoApplication
{
   private const string RegRunSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
   private const string RegRunOnceSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce";

   /// <summary>
   /// Registry Key point to SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run
   /// </summary>
   private static readonly RegistryKey _rkAppRun;

   /// <summary>
   /// Registry Key point to SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce
   /// </summary>
   private static readonly RegistryKey _rkAppRunOnce;

   static ChoApplication()
   {
       _rkAppRun = Registry.CurrentUser.OpenSubKey(RegRunSubKey, true);
       if (_rkAppRun == null)
          _rkAppRun = Registry.CurrentUser.CreateSubKey(RegRunSubKey);

       _rkAppRunOnce = Registry.CurrentUser.OpenSubKey(RegRunOnceSubKey, true);
       if (_rkAppRunOnce == null)
          _rkAppRunOnce = Registry.CurrentUser.CreateSubKey(RegRunOnceSubKey);
   }

   #region RunAtSystemStartup Overloads

   /// <summary>
   /// Set/Remove the running executable to run at system startup
   /// </summary>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunAtSystemStartup()
   {
       return RunAtSystemStartup(false);
   }

   /// <summary>
   /// Set/Remove the running executable to run at system startup
   /// </summary>
   /// <param name="remove">true, it remove the application from running at system startup.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunAtSystemStartup(bool remove)
   {
       string appLocation = Assembly.GetEntryAssembly().Location;
       return RunAtSystemStartup(Path.GetFileNameWithoutExtension(appLocation), appLocation);
   }

   /// <summary>
   /// Set/Remove the running executable to run at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunAtSystemStartup(string appName)
   {
       return RunAtSystemStartup(appName, false);
   }

   /// <summary>
   /// Set/Remove the running executable to run at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <param name="remove">true, it remove the application from running at system startup.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunAtSystemStartup(string appName, bool remove)
   {
       if (String.IsNullOrEmpty(appName))
          throw new ArgumentException("AppName is missing.");

       return SetValueToRegistry(_rkAppRun, appName, Assembly.GetEntryAssembly().Location, remove);
   }

   /// <summary>
   /// Set/Remove the running executable to run at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <param name="appLocation">Full path of the application to be set.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunAtSystemStartup(string appName, string appLocation)
   {
       return SetValueToRegistry(_rkAppRun, appName, appLocation, false);
   }

   #endregion RunAtSystemStartup Overloads

   #region RunOnceAtSystemStartup Overloads

   /// <summary>
   /// Set/Remove the running executable to run once at system startup
   /// </summary>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunOnceAtSystemStartup()
   {
       return RunOnceAtSystemStartup(false);
   }

   /// <summary>
   /// Set/Remove the running executable to run once at system startup
   /// </summary>
   /// <param name="remove">true, it remove the application from running at system startup.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunOnceAtSystemStartup(bool remove)
   {
       string appLocation = Assembly.GetEntryAssembly().Location;
       return RunOnceAtSystemStartup(Path.GetFileNameWithoutExtension(appLocation), appLocation);
   }

   /// <summary>
   /// Set/Remove the running executable to run once at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunOnceAtSystemStartup(string appName)
   {
       return RunOnceAtSystemStartup(appName, false);
   }

   /// <summary>
   /// Set/Remove the running executable to run once at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <param name="remove">true, it remove the application from running at system startup.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunOnceAtSystemStartup(string appName, bool remove)
   {
       if (String.IsNullOrEmpty(appName))
          throw new ArgumentException("AppName is missing.");

       return SetValueToRegistry(_rkAppRunOnce, String.Format("!{0}", appName), Assembly.GetEntryAssembly().Location, remove);
   }

   /// <summary>
   /// Set/Remove the running executable to run once at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <param name="appLocation">Full path of the application to be set.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   public static bool RunOnceAtSystemStartup(string appName, string appLocation)
   {
       return SetValueToRegistry(_rkAppRunOnce, String.Format("!{0}", appName), appLocation, false);
   }

   #endregion RunOnceAtSystemStartup Overloads

   #region Shared Methods (Private)

   /// <summary>
   /// Set/Remove the running executable to run at system startup
   /// </summary>
   /// <param name="appName">A name to represent the application name in the registry</param>
   /// <param name="appLocation">Full path of the application to be set.</param>
   /// <returns>true, if the operation is successfull. Otherwise, false.</returns>
   private static bool SetValueToRegistry(RegistryKey regKey, string appName, string appLocation, bool remove)
   {
       if (String.IsNullOrEmpty(appName))
          throw new ArgumentException("AppName is missing.");

       if (!remove && String.IsNullOrEmpty(appLocation))
          throw new ArgumentException("AppLocation is missing.");

       if (regKey == null)
          return false;

       if (remove)
          regKey.DeleteValue(appName);
       else
          regKey.SetValue(appName, appLocation);

       return true;
   }

   #endregion Shared Methods (Private)
}

Thursday, November 11, 2010

Tip: Placing WinForm Application to/from the System Tray

In this post, I'll be providing Form extension methods to place WinForm application to and from the System Tray. Below are the two main methods used

  • HideToTray() - Hide the main form to system tray. You have option of passing context menu explicitly to set as shortcut menu, if you want. Otherwise the helper method use the form's ContextMenuStrip or ContextMenu property to set as shortcut menu for System Tray.
  • RestoreFromTray() - Restore the system tray application to WinForm normal state.
How to use:
private void frmMain_Resize(object sender, EventArgs e)
{
   if (this.WindowState == FormWindowState.Minimized)
      this.HideToTray();
}
Or
protected override void OnLoad(EventArgs e)
{
   this.HideToTray();
   base.OnLoad(e);
}
Please feel free to use these methods for your development. Drop your comments if you like to.

public static class ChoFormEx
{
   /// <summary>
   /// Default shortcut menu, if the form does not have context menu attached to it.
   /// </summary>
   private static ContextMenuStrip _defaultTrayShortcutMenu;

   /// <summary>
   /// Static Constructor
   /// </summary>
   static ChoFormEx()
   {
       _defaultTrayShortcutMenu = new ContextMenuStrip();
       _defaultTrayShortcutMenu.Items.Add("&Restore", null, (sender, e) =>
          {
              ToolStripItem stripItem = sender as ToolStripItem;
              if (stripItem != null)
              {
                 Form mainForm = stripItem.Tag as Form;
                 mainForm.RestoreFromTray();
              }
          });
       _defaultTrayShortcutMenu.Items.Add("E&xit", null, (sender, e) =>
          {
              ToolStripItem stripItem = sender as ToolStripItem;
              if (stripItem != null)
              {
                 Form mainForm = stripItem.Tag as Form;
                 NotifyIcon trayIcon = mainForm.Tag as NotifyIcon;
                 if (trayIcon != null)
                 {
                     trayIcon.Dispose();
                     mainForm.Tag = null;
                 }
              }
              Application.Exit();
          });
   }

   /// <summary>
   /// Convert a Windows Application to Tray Application
   /// </summary>
   /// <param name="frm">A window form used to construct NotifyIcon object.</param>
   /// <returns>A component that creates an icon in the notification area.</returns>
   public static NotifyIcon HideToTray(this Form frm)
   {
       if (frm.ContextMenuStrip != null)
          return HideToTray(frm, frm.ContextMenuStrip);
       else
          return HideToTray(frm, frm.ContextMenu);
   }

   /// <summary>
   /// Convert a Windows Application to Tray Application
   /// </summary>
   /// <param name="frm">A window form used to construct NotifyIcon object.</param>
   /// <param name="menuStrip">A context menu strip used to set as shortcut menu for NotifyIcon object.</param>
   /// <returns>A component that creates an icon in the notification area.</returns>
   public static NotifyIcon HideToTray(this Form frm, ContextMenuStrip menuStrip)
   {
       return HideToTray(frm, menuStrip, null);
   }

   /// <summary>
   /// Convert a Windows Application to Tray Application
   /// </summary>
   /// <param name="frm">A window form used to construct NotifyIcon object.</param>
   /// <param name="menu">A context menu used to set as shortcut menu for NotifyIcon object.</param>
   /// <returns>A component that creates an icon in the notification area.</returns>
   public static NotifyIcon HideToTray(this Form frm, ContextMenu menu)
   {
       return HideToTray(frm, null, menu);
   }

   /// <summary>
   /// Restore the window application to normal from Tray
   /// </summary>
   /// <param name="frm">A window form used to construct NotifyIcon object.</param>
   public static void RestoreFromTray(this Form frm)
   {
       Form mainForm = Application.OpenForms.Count > 0 ? Application.OpenForms[0] : frm;
       if (mainForm != null)
       {
          mainForm.Visible = true;
          mainForm.ShowInTaskbar = true;
          mainForm.WindowState = FormWindowState.Normal;
          NotifyIcon trayIcon = mainForm.Tag as NotifyIcon;
          if (trayIcon != null)
          {
             trayIcon.Dispose();
              mainForm.Tag = null;
          }
       }
   }

   /// <summary>
   /// Helper method to convert application to Tray application.
   /// menuStrip object / menu object / default tray menu will be used as Shortcut menu in the order it is specified.
   /// </summary>
   /// <param name="frm">A window form used to construct NotifyIcon object.</param>
   /// <param name="menuStrip">A context menu strip used to set as shortcut menu for NotifyIcon object.</param>
   /// <param name="menu">A context menu used to set as shortcut menu for NotifyIcon object.</param>
   /// <returns>A component that creates an icon in the notification area.</returns>
   private static NotifyIcon HideToTray(Form frm, ContextMenuStrip menuStrip, ContextMenu menu)
   {
       Form mainForm = Application.OpenForms.Count > 0 ? Application.OpenForms[0] : frm;

       if (menuStrip == null && menu == null)
       {
          foreach (ToolStripItem tsi in _defaultTrayShortcutMenu.Items)
              tsi.Tag = mainForm;

          menuStrip = _defaultTrayShortcutMenu;
       }

       NotifyIcon trayIcon = new NotifyIcon();
       trayIcon.Text = frm.Text;
       trayIcon.Icon = frm.Icon;
       if (menuStrip != null)
          trayIcon.ContextMenuStrip = menuStrip;
       else
          trayIcon.ContextMenu = menu;
       trayIcon.Visible = true;
       trayIcon.Tag = frm;

       mainForm.Visible = false;
       mainForm.ShowInTaskbar = false;
       mainForm.Tag = trayIcon;

       return trayIcon;
   }
}