Click here to Skip to main content
15,891,372 members
Articles / Mobile Apps / Windows Mobile

Task Manager for Windows Mobile and Windows CE

Rate me:
Please Sign up or sign in to vote.
4.51/5 (23 votes)
30 Nov 2008CPOL10 min read 112.6K   7.3K   79  
Source code for writing your own Task Manager for Windows Mobile or Windows CE based devices
//#define BUG1  // Undefine to fix bug1
//#define BUG2  // Undefine to alternative solution for bug2

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CETaskManager
{
    public partial class Form1 : Form, ToolBoxLib._ICpuLoadEvents /* interface implementation required when we subcribe manually*/
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            // Customize
            this.tabPage1.Text = "Processes";
            this.tabPage2.Text = "Performance";
            this.tabPage3.Text = "About";
            this.label1.Text = "Windows Mobile Task Manager\n\nWritten by\nWerner Willemsens and\nKurt Mampaey\n\nCopyright (c) 2008\n";

            // Add table styles
            this.dataGrid1.TableStyles.Add(new DataGridTableStyle());
            this.dataGrid1.TableStyles[0].MappingName = "ProcessTable";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[0].MappingName = "ProcessName";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ProcessName"].Width = 100;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ProcessName"].HeaderText = "ProcessName";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[1].MappingName = "ProcessId";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ProcessId"].Width = 60;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ProcessId"].HeaderText = "ProcessId";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[2].MappingName = "ThreadCount";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ThreadCount"].Width = 25;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ThreadCount"].HeaderText = "ThreadCount";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[3].MappingName = "BaseAddress";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["BaseAddress"].Width = 60;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["BaseAddress"].HeaderText = "BaseAddress";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[4].MappingName = "HeapSize";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["HeapSize"].Width = 60;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["HeapSize"].HeaderText = "HeapSize";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[5].MappingName = "TotalMemory";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["TotalMemory"].Width = 60;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["TotalMemory"].HeaderText = "TotalMemory";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[6].MappingName = "CommittedMemory";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["CommittedMemory"].Width = 60;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["CommittedMemory"].HeaderText = "CommittedMemory";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[7].MappingName = "ReservedMemory";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ReservedMemory"].Width = 60;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["ReservedMemory"].HeaderText = "ReservedMemory";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles.Add(new DataGridTextBoxColumn());
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles[8].MappingName = "DllCount";
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["DllCount"].Width = 25;
            this.dataGrid1.TableStyles["ProcessTable"].GridColumnStyles["DllCount"].HeaderText = "DllCount";

            // Position data grid
            this.dataGrid1.Location = new Point(0, 0);
            this.dataGrid1.Size = new Size(this.Width, this.Height);

            // Add ContextMenu to data grid
            this.dataGrid1.ContextMenu = new ContextMenu();
            MenuItem item1 = new MenuItem();
            item1.Text = "&End Process";
            item1.Click += new EventHandler(dataGrid1_EndProcess_Click);
            this.dataGrid1.ContextMenu.MenuItems.Add(item1);
            MenuItem item2 = new MenuItem();
            item2.Text = "&Update Process list";
            item2.Click += new EventHandler(dataGrid1_UpdateProcessList_Click);
            this.dataGrid1.ContextMenu.MenuItems.Add(item2);

            // Add chart
            this.m_chart = new CEchart.ProcessChart();
            this.m_chart.Location = new Point(0, 0);
            this.m_chart.Size = new Size(this.tabPage2.Width, this.tabPage2.Height);
            this.tabPage2.Controls.Add(m_chart);

            // Create member objects
            m_cpuLoad = new ToolBoxLib.CpuLoadClass();
            m_processList = new ToolBoxLib.ProcessListClass();
            m_system = new ToolBoxLib.SystemClass();

#if (BUG1)
            // Automatic subscription to COM event (but has bugs)
            m_cpuLoad.Measurement += new ToolBoxLib._ICpuLoadEvents_MeasurementEventHandler(delegate(int cpuLoad) { System.Diagnostics.Debug.WriteLine("Called anonymously..."); });
            m_cpuLoad.Measurement += new ToolBoxLib._ICpuLoadEvents_MeasurementEventHandler(cpuLoad_Measurement);
#else // Fix for BUG1
            // Manual (bug free) subscription to COM event
            System.Runtime.InteropServices.ComTypes.IConnectionPointContainer iCPC = (System.Runtime.InteropServices.ComTypes.IConnectionPointContainer)m_cpuLoad;
            System.Runtime.InteropServices.ComTypes.IConnectionPoint iCP;
            Guid IID_ICpuLoadEvents = new Guid("9C6705E3-E8F9-4692-8FC8-FE15B6226022"); // typeof(ToolBoxLib._ICpuLoadEvents).Guid();
            iCPC.FindConnectionPoint(ref IID_ICpuLoadEvents, out iCP);
            iCP.Advise(this, out m_cookie);
#endif

            m_cpuLoad.Start();

            // Auto update every 3sec?
            m_timer = new System.Windows.Forms.Timer();
            m_timer.Tick += new EventHandler(AutoRefresh);
            m_timer.Interval = 1000;
            m_timer.Enabled = false; // true; --> instead we use 1sec timer from ToolBoxLib._ICpuLoadEvents
        }

        /// <summary>
        /// Proper shutdown when application closes
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Closing(object sender, CancelEventArgs e)
        {
            m_cpuLoad.Stop();

#if (BUG1)
            // Automatic un-subscription to COM event (but has bugs)
            m_cpuLoad.Measurement -= new ToolBoxLib._ICpuLoadEvents_MeasurementEventHandler(delegate(int cpuLoad) { System.Diagnostics.Debug.WriteLine("Called anonymously..."); });
            m_cpuLoad.Measurement -= new ToolBoxLib._ICpuLoadEvents_MeasurementEventHandler(cpuLoad_Measurement);
#else // Fix for BUG1
            // Manual (bug free) un-subscription to COM event
            System.Runtime.InteropServices.ComTypes.IConnectionPointContainer iCPC = (System.Runtime.InteropServices.ComTypes.IConnectionPointContainer)m_cpuLoad;
            System.Runtime.InteropServices.ComTypes.IConnectionPoint iCP;
            Guid IID_ICpuLoadEvents = new Guid("9C6705E3-E8F9-4692-8FC8-FE15B6226022"); // typeof(ToolBoxLib._ICpuLoadEvents).Guid();
            iCPC.FindConnectionPoint(ref IID_ICpuLoadEvents, out iCP);
            iCP.Unadvise(m_cookie);
#endif

            m_cpuLoad = null;
        }

        /// <summary>
        /// Resize
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Resize(object sender, EventArgs e)
        {
            this.tabControl1.Size = new Size(this.Width - 5, this.Height - this.statusBar1.Height);

            if (this.dataGrid1 != null)
            {
                this.dataGrid1.Size = new Size(this.tabPage1.Width, this.tabPage1.Height);
            }
            if (m_chart != null)
            {
                this.m_chart.Size = new Size(this.tabPage2.Width, this.tabPage2.Height);
            }
        }

        /// <summary>
        /// Implementation for ToolBoxLib._ICpuLoadEvents
        /// </summary>
        /// <param name="cpuLoad"></param>
        public void Measurement(int cpuLoad)
        {
            // Dispatch further
            cpuLoad_Measurement(cpuLoad);
        }

        /// <summary>
        /// Callback that will process cpuLoad Measurement event
        /// </summary>
        /// <param name="cpuLoad"></param>
        void cpuLoad_Measurement(int cpuLoad)
        {
            if (this.InvokeRequired == true)
            {
                this.Invoke(new cpuLoad_MeasurementDelegate(cpuLoad_Measurement), new object[] { cpuLoad } );
                return;
            }
            m_chart.AddValue(cpuLoad);
            m_system.Update();
            if (this.tabControl1.SelectedIndex == 0)
            {
                long available = m_system.PhysicalMemoryTotal - m_system.PhysicalAvailable;
                long total = m_system.PhysicalMemoryTotal;
                long percentage = (available * 100) / total;
                this.statusBar1.Text = "Memory load " + available.ToString() + "/" + total.ToString() + " [" + percentage.ToString() + "%]";
            }
            else
            {
                this.statusBar1.Text = "Cpu load " + cpuLoad.ToString() + "%";
            }

            // If you wish to contineously to update the ProcessList, uncomment this line
            // To test BUG2 more easily, uncomment this line to Update the ProcessList contineously
            //FillDataGrid();
        }

        /// <summary>
        /// Timer callback function (alternative for 1sec timer from ToolBoxLib._ICpuLoadEvents)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AutoRefresh(Object sender, EventArgs e)
        {
            try
            {
                this.Invoke((EventHandler)delegate(Object _sender, EventArgs _e) { FillDataGrid(); });
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Failure : " + ex.Message);
            }
        }

        /// <summary>
        /// Update the Grid with all running processes and their properties
        /// Data is delivered by COM coclass ProcessList and Process
        /// </summary>
        private void FillDataGrid()
        {
            string selectedProcessId = "";
            if (this.dataGrid1.CurrentRowIndex != -1)
                selectedProcessId = (string)this.dataGrid1[(this.dataGrid1.CurrentRowIndex), 1];

            // Fill DataGrid
            DataTable dataTable = new DataTable("ProcessTable");
            DataColumn dataColumn;
            DataRow dataRow;

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "ProcessName";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "ProcessId";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "ThreadCount";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "BaseAddress";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "HeapSize";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "TotalMemory";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "CommittedMemory";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "ReservedMemory";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            dataColumn = new DataColumn();
            dataColumn.DataType = System.Type.GetType("System.String");
            dataColumn.ColumnName = "DllCount";
            dataColumn.ReadOnly = true;
            dataTable.Columns.Add(dataColumn);

            // This will create a snapshot of the running processes
            m_processList.Update();

            if (m_processList.Count == 0) // CF can not deal with an empty m_processList??
            {
                System.Diagnostics.Debug.WriteLine("Failure : process list was empty");
            }
            else
            {
#if (BUG2)
                foreach (ToolBoxLib.IProcess process in m_processList)
                {
#else // alternative for BUG2. Can work because we implement Count property too.
                for (int i = 0; i < m_processList.Count; i++)
                {
                    ToolBoxLib.IProcess process = m_processList.Item(i);
#endif
                    dataRow = dataTable.NewRow();
                    dataRow["ProcessName"] = process.Name;
                    dataRow["ProcessId"] = String.Format("{0:X8}", process.Pid);
                    dataRow["ThreadCount"] = process.ThreadCount.ToString();
                    dataRow["BaseAddress"] = String.Format("{0:X8}", process.BaseAddress);
                    dataRow["HeapSize"] = process.HeapSize.ToString();
                    dataRow["TotalMemory"] = process.VirtualMemory.ToString();
                    dataRow["CommittedMemory"] = process.VirtualMemoryCommitted.ToString();
                    dataRow["ReservedMemory"] = process.VirtualMemoryReserved.ToString();
                    dataRow["DllCount"] = process.DllCount.ToString();
                    dataTable.Rows.Add(dataRow);
                }
            }

            this.dataGrid1.DataSource = dataTable;

            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                // This processName row = previous selected processName?
                if (((string)this.dataGrid1[i, 1]).Equals(selectedProcessId))
                {
                    this.dataGrid1.CurrentRowIndex = i;
                    break;
                }
            }
        }

        /// <summary>
        /// tabControl1_SelectedIndexChanged event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.tabControl1.SelectedIndex == 0)
            {
                FillDataGrid();
            }
        }

        /// <summary>
        /// dataGrid1_MouseDown event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGrid1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                this.dataGrid1.ContextMenu.Show(this.dataGrid1, new Point(e.X, e.Y));
            }
        }

        void dataGrid1_EndProcess_Click(object sender, EventArgs e)
        {
            // Any item selected?
            if (this.dataGrid1.CurrentRowIndex < 0)
            {
                return;
            }

            // item.Text should be "&End Process"
            MenuItem item = (MenuItem)sender;
            // What is the "ProcessName"
            string processName = (string)this.dataGrid1[this.dataGrid1.CurrentRowIndex, 0];
            // What is the "ProcessId"
            int processId = -1;
#if (BUG2)
            foreach (ToolBoxLib.IProcess process in m_processList)
            {
#else  // alternative for BUG2. Can work because we implement Count property too.
            for (int i = 0; i < m_processList.Count; i++)
            {
                ToolBoxLib.IProcess process = m_processList.Item(i);
#endif
                if (process.Name == processName)
                {
                    processId = process.Pid;
                    break;
                }
            }
             
            if (DialogResult.Yes == MessageBox.Show("Are you sure you want to terminate process '" + processName + "'?", "End Process", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2))
            {
                if (m_system.EndProcess(processId) == true)
                {
                    FillDataGrid();
                }
            }
        }

        /// <summary>
        /// dataGrid1_UpdateProcessList_Click event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void dataGrid1_UpdateProcessList_Click(object sender, EventArgs e)
        {
            FillDataGrid();
        }

        /// <summary>
        /// Form1_GotFocus event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_GotFocus(object sender, EventArgs e)
        {
            FillDataGrid();
        }

        public delegate void cpuLoad_MeasurementEventHandler(int cpuLoad);

#if (!BUG1)
        private int m_cookie = 0;
#endif
        private CEchart.ProcessChart m_chart = null;
        private delegate void cpuLoad_MeasurementDelegate(int cpuLoad);

        private ToolBoxLib.CpuLoadClass m_cpuLoad = null;
        private ToolBoxLib.ProcessListClass m_processList = null;
        private ToolBoxLib.SystemClass m_system = null;

        private System.Windows.Forms.Timer m_timer = null;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Team Leader
Belgium Belgium
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions