Click here to Skip to main content
11,575,921 members (57,792 online)
Click here to Skip to main content
Add your own
alternative version

Task Manager for Windows Mobile and Windows CE

, 30 Nov 2008 CPOL 67.8K 5K 73
Source code for writing your own Task Manager for Windows Mobile or Windows CE based devices
CETaskManager_demo.zip
Documents and Settings
Werner
My Documents
The CodeProject
CETaskManager_V2
CETaskManager.CAB
CETaskManager_src.zip
CETaskManager
CAB
TaskManager.vddproj
CEChart
bin
Release
CE
CEchart.dll
CEchart.pdb
CETaskManager
Properties
Settings.settings
Res
TaskMgr.ico
TaskMgr.ico
ToolBox
Idl
Res
CpuLoad.rgs
CpuLoadDCOM.rgs
Process.rgs
ProcessDCOM.rgs
ProcessList.rgs
ProcessListDCOM.rgs
System.rgs
SystemDCOM.rgs
ToolBox.def
ToolBox.rgs
ToolBoxdcom.rgs
Src
Threads
Tools
Windows
ToolBox.vcproj.ISAS5.Werner.user
ToolBoxTest
//#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)

Share

About the Author

Werner Willemsens
Team Leader
Belgium Belgium
No Biography provided

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150603.1 | Last Updated 30 Nov 2008
Article Copyright 2008 by Werner Willemsens
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid