Список работ

C#: производительность интернет-процессов

Курсовая работа по дисциплине Программная инженерия

Ефимова П. В., А-05-14

Содержание

1. Постановка задачи

Разрабатывается приложение, воспроизводящее скорость передачи данных (байт/с) интернет-процессов на локальном компьютере, включающее:

Приложение выполняется на платформе Visual Studio 2013, язык программирования C#.

2. Порядок решения задачи

Используются счетчики производительности - объекты класса PerformanceCounter, определяющие скорость передачи и приема интернет-данных. Категория счетчика имеет имя Network Interface; имена счетчиков отправки и приема данных соответственно Bytes Sent/sec и Bytes Received/sec. (Список возможных имен категорий можно посмотреть в приложении.)
Реализована следующая последовательность действий:

  1. Создать объект pCC класса PerformanceCounterCategory пространства имен System.Diagnostics, представляющий категорию Network Interface счетчика производительности.
  2. При помощи метода GetInstanceNames этого класса извлечь список имен экземпляров указанной категории (Network Interface).
  3. Присвоить переменной instance имя соответствующего экземпляра. В случае проводного интернета – это нулевой экземпляр, в случае Wi-Fi – первый. Возможные имена экземпляров:
  4. Создать счетчики производительности для фиксации скорости передачи и приема интернет-данных.
  5. Каждые 1000 миллисекунд (интервал таймера):
    1. Сформировать массив proc активных процессов компьютера (метод GetProcesses класса System.Diagnostics.Process).
    2. Для каждого процесса массив proc
      1. Считать показания (sizeRec и sizeSent) счетчиков производительности (метод NextValue класса PerformanceCounter).
      2. Пополнить данными о процессе Grid-таблицу и xml-файл.

Для каждого процесса фиксируются следующие сведения:

По данным xml-файл формируются отчеты История процесса и Итоги.
Имя xml-файла хранит файл параметров path.txt, расположенный в папке запускаемого приложения (на данном этапе в файле один параметр).

3. Реализация приложения

3.1. Форма приложения

Показана на рис. 1.

Используются счетчики производительности

Рис. 1. Форма приложения

Форма отображает производительность передачи интернет-трафика, позволяет выбрать xml-файл для фиксации данных, начать и остановить работу со счетчиками производительности, вывести отчеты История (выбранного процесса) и Итоги.

3.2. Класс processing

Для чтения и фиксации показаний счетчиков производительности создан класс processing.

3.2.1. Поля класса processing

Xml-документ:
        protected XmlDocument xmlDoc = new XmlDocument();

Переменные для формирования Excel-отчета:
        // Период наблюдения
        protected DateTime sTimeMax, sTimeMin;
        // Список порций для отчетов История и Итоги. Формируется в LoadXML()
        protected List<printList> printListXML = new List<printList>();
        protected Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();

Структура для отчетов История и Итоги, выводимых в Excel-файл:
        public struct printList
        {
            public string pName; // Имя процесса
            public int pType; // Тип трафика (0 - прием, 1 - передача)
            public string psTime; // Время фиксации показаний счетчиков производительности
            public double pSize; // Производительность (скорость) байт/с
            public int mnt; // Всегда равен 1 (используется при группировке данных)
            public printList(string pName2, int pType2, string psTime2, double pSize2, int mnt2)
            {
                pName = pName2;
                pType = pType2;
                psTime = psTime2;
                pSize = pSize2;
                mnt = mnt2;
            }
        }

3.2.2. Методы класса processing

Проверка существования файла параметров path.txt. Если файл не существует, то он создается. Результат функции: полное имя xml-файла, хранящего замеренные данные.
private string checkFile(string fileName)

Загрузка диалога для сохранения пути к xml-файлу.
public string loadPath(string fileName)

Вывод данных, хранимых в xml-файле, в Grid-таблицу и имен процессов в ComboBox.
public void initData(System.Windows.Forms.ComboBox comboBox1, ref string fileName)

Пополняет Grid и xml результатами измерения
private void oneProc(string procName, string procType, double performance, string fileName)

Вывод текущих показаний счетчиков производительности в Grid-таблицу и в xml-файл.
public void runCounters(PerformanceCounter pCSent, PerformanceCounter pCReceived, string fileName)

Запись текущих показаний в xml-файл.
private void outputInXml(string fileName)

Загрузка данных из xml-файла в список printListXML.
private bool LoadXML(string fileName)

Заполнение Grid-таблицы данными xml-файла.
private void gridFromXML (string fileName)

Формирование отчета Итоги в Excel-файл.
public void totals(string fileName)

Формирование списка ComboBox (содержит отсортированный перечень имен процессов).
public void makeChoice(System.Windows.Forms.ComboBoxcBox, string fileName)

Формирование отчета История процесса в Excel-файл.
public void procHistory(string selectedName, string fileName)

Вывод полученного трафика выбранного процесса в отчет История процесса (вспомогательный для procHistory метод).
private void creatExcelRec(string selectedName, string[] arrsTimeRec, double[] arrSizeRec, Excel.Worksheet xlWorkSheet)

Вывод отправленного трафика выбранного процесса в отчет История процесса (вспомогательный для procHistory метод)
private void creatExcelSent(int count, string selectedName, string[] arrsTimeSent, double[] arrSizeSent, Excel.Worksheet xlWorkSheet)

3.3. Работа со счетчиками производительности

Чтение показаний счетчиков производительности, добавление данных в Grid-таблицу и пополнение xml-файла обеспечивается следующим методом класса processing:

        // Замеряет скорость передачи данных интернет-процессов и выводит данные в Grid и xml-файл
        public void runCounters(PerformanceCounter pCSent, PerformanceCounter pCReceived, string fileName)
        {
            System.Diagnostics.Process[] proc;
            proc = System.Diagnostics.Process.GetProcesses();
            foreach (System.Diagnostics.Process i in proc)
            {
                double perfRec = pCReceived.NextValue(); // Производительность приема данных
                double perfSent = pCSent.NextValue(); // Производительность передачи данных
                // Принятые данные
                if (perfRec > 0) oneProc(i.ProcessName, "0", perfRec, fileName);
                // Отправленные данные
                if (perfSent > 0) oneProc(i.ProcessName, "1", perfSent, fileName);
            }
        }

Метод runCounters вызывается при каждом срабатывании таймера:

        private void timer1_Tick(object sender, EventArgs e)
        {
            labelTick.Text = "Tick " + (++nTicks);
            // Снимаем показания счетчиков производительности
            counter.runCounters(pCSent, pCReceived, fileName);
        }

3.4. Работа с xml-файлом

3.4.1. Структура xml-файла

Xml-файл хранит сведения о замеренном интернет-трафике и имеет следующую структуру:

<?xml version="1.0" encoding="utf-8"?>
<traffic>
<!-- Описание порции данных -->
<!-- Имя процесса -->
<!-- Вид порции: 0 - входящие данные; 1 - исходящие -->
<!-- Время измерения показаний счетчиков производительности -->
<!-- Скорость передачи данных в байт/с -->
<portion>
    <processName>opera</processName>
    <type>0</type>
    <sTime>25.11.2016 17:02:08.76</sTime>
    <size>67986,5234375</size>
</portion>
<portion>
    <processName>opera</processName>
    <type>1</type>
    <sTime>25.11.2016 17:02:10.138</sTime>
    <size>14115,611328125</size>
</portion>
<portion>

</portion>
</traffic>

3.4.2. Путь к xml-файлу

Путь к xml-файлу хранится в файле параметров path.txt, который размещен в папке с приложением. Если при запуске приложения файл path.txt не найден, то он будет создан программой, и будет открыт диалог выбора xml-файла (рис. 2).

Нужно выбрать xml-файл

Рис. 2. Выбор к xml-файла

Полное имя xml-файла будет сохранено в файле параметров path.txt.
Также диалог выбора xml-файла открывается после нажатия на кнопку Файл формы приложения (см. рис. 1).

3.4.3. Вывод данных в xml-файл

Пополнение xml-файла обеспечивает следующая процедура класса processing:

        // Пополняет xml-файл данными о процессах и скорости передачи данных
        private void outputInXml(string procName, string procType, string procsTime, string procPerf, string fileName)
        {
            xmlDoc.Load(fileName);
            XmlElement xmlRoot = xmlDoc.DocumentElement; // Корневой элемент
            XmlElement elem_portion = xmlDoc.CreateElement("portion");
            XmlElement elem_processName = xmlDoc.CreateElement("processName");
            XmlElement elem_type = xmlDoc.CreateElement("type");
            XmlElement elem_sTime = xmlDoc.CreateElement("sTime");
            XmlElement elem_size = xmlDoc.CreateElement("size");
            xmlRoot.AppendChild(elem_portion);
            elem_portion.AppendChild(elem_processName);
            elem_processName.AppendChild(xmlDoc.CreateTextNode(procName));
            elem_portion.AppendChild(elem_type);
            elem_type.AppendChild(xmlDoc.CreateTextNode(procType));
            elem_portion.AppendChild(elem_sTime);
            elem_sTime.AppendChild(xmlDoc.CreateTextNode(procsTime));
            elem_portion.AppendChild(elem_size);
            elem_size.AppendChild(xmlDoc.CreateTextNode(procPerf));
            xmlDoc.Save(fileName);
        }

Процедура outputInXml вызывается при обнаружении факта передачи и/или приема интернет-данных.

3.5. Формирование отчетов

Отчеты формируются по данным xml-файла, описанного выше, в виде Excel-документов.
Можно вывести отчеты Итоги (рис. 3) и История процесса (рис. 4).

Отчет Итоги в Excel

Рис. 3. 10 строк отчета Итоги

Отчет История процесса в Excel

Рис. 4. Отчет по процессу

Процесс для отчета выбирается из имеющегося в форме приложения (рис. 1) раскрывающегося списка. Формирование раскрывающего списка обеспечивает следующая процедура класса processing:

        // Формирует comboBox по данным xml-файла
        public void makeChoice(System.Windows.Forms.ComboBox cBox, string fileName)
        {
            if (!LoadXML(fileName)) return;
            // Группировка и сортировка по имени процесса
            var printListName = printListXML.GroupBy(p => p.pName).Select(
                grp => new printList { pName = grp.Key }).OrderBy(p => p.pName);
            string[] arrPrcAll = printListName.Select(p => p.pName).ToArray();
            cBox.Items.Clear();
            cBox.Items.AddRange(arrPrcAll);
        }

Порядок формирования отчета см. реферате Вывод отчета в Excel.

Заключение

Создано приложение, обеспечивающее обработку интернет-трафика и вывод отчетов по итогам работы программы.
В последующем планируется в множестве процессов, формирующих интернет-трафик, выделять нежелательные и вредоносные и сохранять для последующего анализа передаваемые ими данные.
Для этих целей может быть употреблен NetworkInterface пространства имен System.Net.NetworkInformation:

        if (!NetworkInterface.GetIsNetworkAvailable()) return;
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface ni in interfaces)
            {
                Console.WriteLine("Bytes Sent: " + ni.GetIPv4Statistics().BytesSent);
                Console.WriteLine("Bytes Rec: " + ni.GetIPv4Statistics().BytesReceived);
            }

Также представляется полезным вместо непосредственного заполнения Grid-таблицы использовать ее привязку к источнику данных (свойство DataSource).
Кроме того, пополнение xml-файла следует производить в конце сеанса либо по данным Grid-таблицы, либо по данным ассоциированного с Grid источника данных. Это позволит высвободить ресурсы для обработки анализируемых интернет-процессов.
Процедуры фиксации сетевого трафика можно запускать в отдельном, обладающем высоким приоритетом потоке (нити).

Приложение 1. Код программы

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Xml;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel; // Создаем псевдоним, чтобы не возникло конфликта
using System.IO;

namespace plnVC
{
    public partial class Form1 : Form
    {
        string fileName; // Имя xml-файла
        processing counter;
        PerformanceCounter pCSent;
        PerformanceCounter pCReceived;
        public static Form1 Instance;

        public Form1()
        {
            InitializeComponent();
            Instance = this;
            timer1.Enabled = false;
            timer1.Interval = 1000;
            labelTick.Text = "";
            labelFile.Text = "";
            labelProc.Text = "";
            initGrid();
            counter = new processing();
            counter.initData(comboBox1, ref fileName);
            // Создаем счетчики производительности
            string category = "Network Interface";
            // Категория счетчика производительности
            PerformanceCounterCategory pCC = new PerformanceCounterCategory(category);
            // В Случае Wi-Fi указываем [1]. В случае проводного интернета - [0]
            string instance = pCC.GetInstanceNames()[1];
            // Счетчики производительности передачи и приема данных
            pCSent = new PerformanceCounter(category, "Bytes Sent/sec", instance);
            pCReceived = new PerformanceCounter(category, "Bytes Received/sec", instance);
            //
            bool enabled = !String.IsNullOrEmpty(fileName);
            button1.Enabled = enabled; // Старт
            button2.Enabled = true; // Закрыть
            button3.Enabled = true; // Файл
            button4.Enabled = false; // Стоп
            button5.Enabled = enabled; // История
            button6.Enabled = enabled; // Итоги
            comboBox1.Enabled = enabled;
        }
        // Формирует столбец Grid-таблицы
        private DataGridViewColumn oneColumn(string headerText, string name)
        {
            var column = new DataGridViewColumn();
            column.HeaderText = headerText;
            column.Name = name; // Имя колонки, его можно использовать вместо обращений по индексу
            column.Frozen = true; // Флаг говорящий, что данная колонка всегда отображается на своем месте
            column.CellTemplate = new DataGridViewTextBoxCell(); // Тип колонки
            return column;
        }
        // Формирует Grid-таблицу
        private void initGrid()
        {
            dataGridView1.Columns.Add(oneColumn("Process name", "name"));
            dataGridView1.Columns.Add(oneColumn("Type", "type"));
            dataGridView1.Columns.Add(oneColumn("Start time", "startDate"));
            dataGridView1.Columns.Add(oneColumn("Performance", "performance"));
            dataGridView1.AllowUserToAddRows = false;
            for (int k = 0; k < 4; k++)
            {
                dataGridView1.Columns[k].Width = 155;
                dataGridView1.Columns[k].ReadOnly = true;
            }
            dataGridView1.Columns["type"].Width = 62;
            dataGridView1.Columns["type"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;
            dataGridView1.Columns["performance"].Width = 100;
            dataGridView1.Columns["performance"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomRight;
        }
        // Файл
        private void button3_Click(object sender, EventArgs e)
        {
            fileName = counter.loadPath(fileName);
            if (!String.IsNullOrEmpty(fileName)) counter.initData(comboBox1, ref fileName);
            comboBox1.SelectedItem = "";
            comboBox1.Text = "";
        }
        // Старт
        private void button1_Click(object sender, EventArgs e)
        {
            nTicks = 0;
            timer1.Enabled = true;
            timer1.Start();
            button1.Enabled = false; // Старт
            button3.Enabled = false; // Файл
            button4.Enabled = true; // Стоп
            button5.Enabled = false; // История
            button6.Enabled = false; // Итоги
            comboBox1.Enabled = false;
        }
        // Стоп
        private void button4_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            timer1.Enabled = false;
            labelTick.Text = "";
            button1.Enabled = true;
            button3.Enabled = true; // Файл
            button4.Enabled = false; // Стоп
            button5.Enabled = true; // История
            button6.Enabled = true; // Итоги
            comboBox1.Enabled = true;
            // Обновляем comboBox1
            counter.makeChoice(comboBox1, fileName);
        }
        // Закрыть форму
        private void button2_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            Close();
        }
        // Отчет История
        private void button5_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(comboBox1.Text))
                MessageBox.Show("Выберите процесс!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Question);
            else
            {
                counter.procHistory(comboBox1.Text, fileName); // История выбранного процесса
            }
        }
        // Отчет Итоги
        private void button6_Click(object sender, EventArgs e)
        {
            counter.totals(fileName); // Итоги по всем замерам
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            labelTick.Text = "Tick " + (++nTicks);
            // Снимаем показания счетчиков производительности
            counter.runCounters(pCSent, pCReceived, fileName);
        }
        // Очищает Grid
        public void clearGrid()
        {
            dataGridView1.Rows.Clear();
        }
        public void addRow(string procName, string procType, string procsTime, double procPerf)
        {
            dataGridView1.Rows.Add(procName, procType, procsTime, procPerf);
        }
        public void labelText(string text, int k)
        {
            switch (k)
            {
                case 1: labelFile.Text = text; break;
                case 2: labelProc.Text = text; break;
            }
        }
    }
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    public class processing
    {
        protected XmlDocument xmlDoc = new XmlDocument();

        // Читает из файла параметров имя xml-файла
        private string checkFile(string fileName)
        {
            string filePath = "path.txt";
            if (System.IO.File.Exists(filePath))
            {
                fileName = System.IO.File.ReadAllText(filePath);
                if (fileName != "")
                {
                    Form1.Instance.labelText("Выбран файл: " + fileName, 1);
                    return fileName;
                }
            }
            return "";
        }
        // Выбирает xml-файл, а затем пишет его имя в файл параметров path.txt
        public string loadPath(string fileName)
        {
            OpenFileDialog OPF = new OpenFileDialog();
            OPF.Filter = "xml-файлы(*.xml)|*.xml";
            DialogResult dlg = OPF.ShowDialog();
            if (dlg == DialogResult.OK)
            {
                fileName = OPF.FileName;
                Form1.Instance.labelText("Выбран файл: " + fileName, 1);
                File.WriteAllText("path.txt", fileName);
                return fileName;
            }
            else
                return "";
        }
        // Заполняет Grid и comboBox по данным xml-файла
        public void initData(System.Windows.Forms.ComboBox comboBox1, ref string fileName)
        {
            fileName = checkFile(fileName);
            if (fileName == "") fileName = loadPath(fileName);
            if (fileName != "")
            {
                gridFromXML(fileName); // Заполняем Grid данными xml-файла
                makeChoice(comboBox1, fileName); // Формируем ComboBox
            }
            Form1.Instance.labelText("Выбран файл: " + fileName, 1);
        }
        // Заполняет Grid данными xml-файла
        private void gridFromXML(string fileName)
        {
            string procName = "", procType = "", procsTime = "", procPerf = "";
            Form1.Instance.clearGrid(); // Очищаем Grid
            xmlDoc.Load(fileName);
            XmlElement xmlRoot = xmlDoc.DocumentElement;
            foreach (XmlNode xmlNode in xmlRoot)
            {
                foreach (XmlNode childnode in xmlNode)
                {
                    if (childnode.Name == "processName") procName = childnode.InnerText;
                    if (childnode.Name == "type") procType = childnode.InnerText;
                    if (childnode.Name == "sTime") procsTime = childnode.InnerText;
                    if (childnode.Name == "size") procPerf = childnode.InnerText;
                }
                Form1.Instance.addRow(procName, procType, procsTime, Math.Round(Convert.ToDouble(procPerf), 1));
            }
        }
        // Пополняет Grid и xml результатами измерения
        private void oneProc(string procName, string procType, double performance, string fileName)
        {
            string procsTime = Convert.ToString(DateTime.Now + "." + DateTime.Now.Millisecond);
            // Добавляем строку Grid
            Form1.Instance.addRow(procName, procType, procsTime, Math.Round(performance, 1));
            // Пополняем xml-файл
            outputInXml(procName, procType, procsTime, Convert.ToString(performance), fileName);
            Form1.Instance.labelText("Добавлен процесс " + procName, 2);
        }
        // Замеряет скорость передачи данных интернет-процессов и выводит данные в Grid и xml-файл
        public void runCounters(PerformanceCounter pCSent, PerformanceCounter pCReceived, string fileName)
        {
            System.Diagnostics.Process[] proc;
            proc = System.Diagnostics.Process.GetProcesses();
            foreach (System.Diagnostics.Process i in proc)
            {
                double perfRec = pCReceived.NextValue(); // Производительность приема данных
                double perfSent = pCSent.NextValue(); // Производительность передачи данных
                // Принятые данные
                if (perfRec > 0) oneProc(i.ProcessName, "0", perfRec, fileName);
                // Отправленные данные
                if (perfSent > 0) oneProc(i.ProcessName, "1", perfSent, fileName);
            }
        }
        // Пополняет xml-файл данными о процессах и скорости передачи данных
        private void outputInXml(string procName, string procType, string procsTime, string procPerf, string fileName)
        {
            xmlDoc.Load(fileName);
            XmlElement xmlRoot = xmlDoc.DocumentElement; // Корневой элемент
            XmlElement elem_portion = xmlDoc.CreateElement("portion");
            XmlElement elem_processName = xmlDoc.CreateElement("processName");
            XmlElement elem_type = xmlDoc.CreateElement("type");
            XmlElement elem_sTime = xmlDoc.CreateElement("sTime");
            XmlElement elem_size = xmlDoc.CreateElement("size");
            xmlRoot.AppendChild(elem_portion);
            elem_portion.AppendChild(elem_processName);
            elem_processName.AppendChild(xmlDoc.CreateTextNode(procName));
            elem_portion.AppendChild(elem_type);
            elem_type.AppendChild(xmlDoc.CreateTextNode(procType));
            elem_portion.AppendChild(elem_sTime);
            elem_sTime.AppendChild(xmlDoc.CreateTextNode(procsTime));
            elem_portion.AppendChild(elem_size);
            elem_size.AppendChild(xmlDoc.CreateTextNode(procPerf));
            xmlDoc.Save(fileName);
        }
        // Отчеты
        // Период наблюдения
        protected DateTime sTimeMax, sTimeMin;
        // Список порций для отчетов История и Итоги. Формируется в LoadXML()
        protected List<printList> printListXML = new List<printList>();
        protected Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
        // Структура для отчетов История и Итоги, выводимых в Excel-файл
        public struct printList
        {
            public string pName; // Имя процесса
            public int pType; // Тип трафика (0 - прием, 1 - передача)
            public string psTime; // Время фиксации показаний счетчиков производительности
            public double pSize; // Производительность (скорость) байт/с
            public int mnt; // Всегда равен 1 (используется при группировке данных)
            public printList(string pName2, int pType2, string psTime2, double pSize2, int mnt2)
            {
                pName = pName2;
                pType = pType2;
                psTime = psTime2;
                pSize = pSize2;
                mnt = mnt2;
            }
        }
        // Формирует список printListXML по данным xml-файла
        private bool LoadXML(string fileName)
        {
            DataSet portionsDS = new DataSet();
            try
            {
                printListXML.Clear();
                printList printCreate;
                string processName; // Имя процеса
                int pTp; // 0 - входящие данные; 1 - исходящие
                DateTime sTime; // Время выполнения измерений
                string sTime2;
                double size; // Размер порции в битах
                string size2; // Символьное представление размера порции
                portionsDS.ReadXml(fileName); // Формируем DataSet portionsDS
                DataTableCollection tbls = portionsDS.Tables; // Коллекция таблиц (у нас одна таблица traffic), содержит отдельные элементы коллекции
                System.Data.DataTable tbl = tbls[0]; // создается таблица с трафиком
                DataRowCollection portions = tbl.Rows; // Коллекция строк таблицы
                // Период наблюдения
                sTimeMax = DateTime.MinValue;
                sTimeMin = DateTime.MaxValue;
                foreach (DataRow portion in portions)
                {
                    processName = Convert.ToString(portion[0]);
                    pTp = Convert.ToInt32(portion["type"]);
                    sTime = Convert.ToDateTime(portion["sTime"]);
                    // Корректируем период наблюдения
                    if (sTime > sTimeMax) sTimeMax = sTime;
                    if (sTime < sTimeMin) sTimeMin = sTime;
                    size2 = Convert.ToString(portion["size"]);
                    size = Convert.ToDouble(size2);
                    sTime2 = Convert.ToString(sTime);
                    printCreate.pName = processName;
                    printCreate.pType = pTp;
                    printCreate.psTime = sTime2;
                    printCreate.pSize = size;
                    printCreate.mnt = 1;
                    printListXML.Add(printCreate);
                }
            }
            catch (System.IO.IOException e)
            {
                MessageBox.Show("Плохой файл " + fileName + ". Сообщение " + e.Message);
                return false;
            }
            finally
            {
                portionsDS.Dispose();
            }
            return true;
        }
        // Формирует по данным xml-файла отчет Итоги
        public void totals(string fileName)
        {
            if (!LoadXML(fileName)) return;
            // Имена всех процессы без повторений в алфавитном порядке
            var printListName = printListXML.GroupBy(p => p.pName).Select(
                grp => new printList { pName = grp.Key }).OrderBy(p => p.pName);
            // Итоги по входящим данным
            var printListRec = printListXML.Where(p => p.pType == 0).GroupBy(p => p.pName).Select(
             grp => new printList { pName = grp.Key, pSize = grp.Sum(p => p.pSize), mnt = grp.Sum(p => p.mnt) }).OrderBy(p => p.pName);
            // Итоги по исходящим данным
            var printListSent = printListXML.Where(p => p.pType == 1).GroupBy(p => p.pName).Select(
             grp => new printList { pName = grp.Key, pSize = grp.Sum(p => p.pSize), mnt = grp.Sum(p => p.mnt) }).OrderBy(p => p.pName);
            // Имена всех процессов
            string[] arrPrcAll = printListName.Select(p => p.pName).ToArray();
            // Входящие порции
            // Имена процессов
            string[] arrPrcIn = printListRec.Select(p => p.pName).ToArray();
            // Суммарные порции входящих данных соответственно процессов "Proc1", "Proc2", "Proc3", "Proc4
            double[] prtnInTotal = printListRec.Select(p => p.pSize).ToArray();
            // Число порций входящих данных
            int[] mntInTotal = printListRec.Select(p => p.mnt).ToArray();
            // Исходящие порции
            // Имена процессов
            string[] arrPrcOut = printListSent.Select(p => p.pName).ToArray();
            // Суммарные порции исходящих данных
            double[] prtnOutTotal = printListSent.Select(p => p.pSize).ToArray();
            // Число порций исходящих данных соответственно процессов "Proc2", "Proc4", "Proc5"
            int[] mntOutTotal = printListSent.Select(p => p.mnt).ToArray();
            if (xlApp == null)
            {
                MessageBox.Show("Excel не найден");
                return;
            }
            Excel.Workbook xlWorkBook;
            Excel.Worksheet xlWorkSheet;
            xlWorkBook = xlApp.Workbooks.Add();
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
            // Заголовки
            xlWorkSheet.Cells[1, 2] = "Интернет-трафик за период с " + sTimeMin + " по " + sTimeMax;
            xlWorkSheet.Cells[2, 2] = "№";
            xlWorkSheet.Cells[2, 3] = "Процесс";
            xlWorkSheet.Cells[2, 4] = "Скорость приема";
            xlWorkSheet.Cells[2, 6] = "Скорость передачи";
            xlWorkSheet.Cells[3, 4] = "Байт/c";
            xlWorkSheet.Cells[3, 5] = "Число порций";
            xlWorkSheet.Cells[3, 6] = "Байт/c";
            xlWorkSheet.Cells[3, 7] = "Число порций";
            int lstClmn = 8; // Следующий после крайнего справа столбца
            // Выравнивание
            for (int i = 2; i < 4; i++)
                for (int j = 2; j < lstClmn; j++)
                    xlWorkSheet.Cells[i, j].HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlCenter;
            // Ширина столбцов
            Excel.Range range = xlWorkSheet.Range["B1:B1", System.Type.Missing];
            range.EntireColumn.ColumnWidth = 7;
            range = xlWorkSheet.Range["C1:C1", System.Type.Missing];
            range.EntireColumn.ColumnWidth = 30;
            range = xlWorkSheet.Range["D1:G1", System.Type.Missing];
            range.EntireColumn.ColumnWidth = 15;
            // Границы ячеек с заголовками
            xlWorkSheet.Cells[2, 2].Borders(1).ColorIndex = 1; // Граница слева
            xlWorkSheet.Cells[2, 3].Borders(1).ColorIndex = 1; // Граница слева
            xlWorkSheet.Cells[2, 3].Borders(2).ColorIndex = 1; // Граница справа
            xlWorkSheet.Cells[2, 5].Borders(2).ColorIndex = 1; // Граница справа
            xlWorkSheet.Cells[2, 7].Borders(2).ColorIndex = 1; // Граница справа
            for (int i = 2; i < lstClmn; i++) xlWorkSheet.Cells[2, i].Borders(3).ColorIndex = 1; // Граница сверху
            for (int i = 4; i < lstClmn; i++) xlWorkSheet.Cells[3, i].Borders(3).ColorIndex = 1; // Граница сверху
            for (int i = 2; i < lstClmn; i++) xlWorkSheet.Cells[3, i].Borders(4).ColorIndex = 1; // Граница снизу
            for (int i = 2; i < lstClmn; i++)
                for (int k = 1; k < 3; k++)
                    xlWorkSheet.Cells[3, i].Borders(k).ColorIndex = 1; // Границы слева и справа
            // Объединение ячеек
            range = xlWorkSheet.get_Range("D2:E2");
            range.Merge(Type.Missing);
            range = xlWorkSheet.get_Range("F2:G2");
            range.Merge(Type.Missing);
            // Всего имен процессов
            int prcMnt = arrPrcAll.Length;
            // Границы ячеек с данными
            for (int i = 4; i < 4 + prcMnt; i++)
                for (int j = 2; j < lstClmn; j++)
                    for (int k = 1; k < 5; k++)
                        xlWorkSheet.Cells[i, j].Borders(k).ColorIndex = 1; // Границы слева, справа, сверху и снизу
            // Выводим номера строк и имена процессов
            int n = 0;
            for (int i = 0; i < prcMnt; i++)
            {
                n++;
                xlWorkSheet.Cells[i + 4, 2] = n;
                xlWorkSheet.Cells[i + 4, 3] = arrPrcAll[i];
            }
            // Число входящих и исходящих данных в итоговых массивах
            int inMnt = arrPrcIn.Length;
            int outMnt = arrPrcOut.Length;
            // Получено
            for (int i = 0; i < prcMnt; i++)
            {
                string prcNm = arrPrcAll[i];
                for (int j = 0; j < inMnt; j++)
                {
                    string prcNm2 = arrPrcIn[j];
                    if (prcNm2 == prcNm)
                    {
                        xlWorkSheet.Cells[i + 4, 4] = Math.Round(prtnInTotal[j] / mntInTotal[j], 1);
                        xlWorkSheet.Cells[i + 4, 5] = mntInTotal[j];
                    }
                }
            }
            // Передано
            for (int i = 0; i < prcMnt; i++)
            {
                string prcNm = arrPrcAll[i];
                for (int j = 0; j < outMnt; j++)
                {
                    string prcNm2 = arrPrcOut[j];
                    if (prcNm2 == prcNm)
                    {
                        xlWorkSheet.Cells[i + 4, 6] = Math.Round(prtnOutTotal[j] / mntOutTotal[j], 1);
                        xlWorkSheet.Cells[i + 4, 7] = mntOutTotal[j];
                    }
                }
            }
            // Показываем отчет, выведенный в Excel
            xlApp.Visible = true;
        }
        // Формирует comboBox по данным xml-файла
        public void makeChoice(System.Windows.Forms.ComboBox cBox, string fileName)
        {
            if (!LoadXML(fileName)) return;
            // Группировка и сортировка по имени процесса
            var printListName = printListXML.GroupBy(p => p.pName).Select(
                grp => new printList { pName = grp.Key }).OrderBy(p => p.pName);
            string[] arrPrcAll = printListName.Select(p => p.pName).ToArray();
            cBox.Items.Clear();
            cBox.Items.AddRange(arrPrcAll);
        }
        public void procHistory(string selectedName, string fileName)
        {
            if (!LoadXML(fileName)) return;
            var printListsTimeRec = printListXML.Where(p => p.pName == selectedName && p.pType == 0).Select(p => p.psTime);
            var printListsTimeSent = printListXML.Where(p => p.pName == selectedName && p.pType == 1).Select(p => p.psTime);
            var printListsSizeRec = printListXML.Where(p => p.pName == selectedName && p.pType == 0).Select(p => p.pSize);
            var printListSizeSent = printListXML.Where(p => p.pName == selectedName && p.pType == 1).Select(p => p.pSize);
            bool flRec = printListsSizeRec.Count() > 0, flSent = printListSizeSent.Count() > 0;
            string[] arrsTimeRec = printListsTimeRec.ToArray();
            double[] arrSizeRec = printListsSizeRec.ToArray();
            string[] arrsTimeSent = printListsTimeSent.ToArray();
            double[] arrSizeSent = printListSizeSent.ToArray();
            if (xlApp == null)
            {
                MessageBox.Show("Excel не найден");
                return;
            }
            int inMnt = arrsTimeRec.Length;
            Excel.Workbook xlWorkBook;
            Excel.Worksheet xlWorkSheet;
            xlWorkBook = xlApp.Workbooks.Add();
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
            if (flRec) creatExcelRec(selectedName, arrsTimeRec, arrSizeRec, xlWorkSheet);
            if (flSent) creatExcelSent(arrsTimeRec.Length, selectedName, arrsTimeSent, arrSizeSent, xlWorkSheet);
            // Показываем отчет, выведенный в Excel
            xlApp.Visible = true;
        }
        private void creatExcelRec(string selectedName, string[] arrsTimeRec, double[] arrSizeRec, Excel.Worksheet xlWorkSheet)
        {
            int inMnt = arrsTimeRec.Length;
            // Заголовки
            xlWorkSheet.Cells[1, 2] = "История процесса " + selectedName + " за период с " + sTimeMin + " по " + sTimeMax;
            xlWorkSheet.Cells[2, 2] = "Время порции";
            xlWorkSheet.Cells[2, 3] = "Скорость, байт/с";
            xlWorkSheet.Cells[3, 2] = "Входящие данные";
            // Выравнивание
            for (int i = 2; i < 4; i++) xlWorkSheet.Cells[2, i].HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlCenter;
            // Границы ячеек
            for (int i = 2; i < 5 + inMnt; i++)
                for (int j = 2; j < 4; j++)
                    for (int k = 1; k < 5; k++)
                    {
                        if (i == 3 || i == 4 + inMnt) continue;
                        xlWorkSheet.Cells[i, j].Borders(k).ColorIndex = 1; // Границы слева, справа, сверху и снизу
                    }
            // Границы ячеек строках 3 и 4 + inMnt с текстом Входящие данные и Исходящие данные
            xlWorkSheet.Cells[3, 2].Borders(1).ColorIndex = 1; // Граница слева
            xlWorkSheet.Cells[3, 3].Borders(2).ColorIndex = 1; // Граница справа
            // Ширина столбцов
            Excel.Range range = xlWorkSheet.Range["B1:D1", System.Type.Missing];
            range.EntireColumn.ColumnWidth = 25;
            // Вывод входящих данных
            for (int i = 0; i < inMnt; i++)
            {
                xlWorkSheet.Cells[i + 4, 2] = arrsTimeRec[i];
                xlWorkSheet.Cells[i + 4, 3] = Math.Round(arrSizeRec[i], 1);
            }
        }
        private void creatExcelSent(int count, string selectedName, string[] arrsTimeSent, double[] arrSizeSent, Excel.Worksheet xlWorkSheet)
        {
            // Число входящих и исходящих данных
            int outMnt = arrsTimeSent.Length;
            if (count == 0)
            {
                // Заголовки
                xlWorkSheet.Cells[1, 2] = "История процесса " + selectedName + " за период с " + sTimeMin + " по " + sTimeMax;
                xlWorkSheet.Cells[2, 2] = "Время порции";
                xlWorkSheet.Cells[2, 3] = "Скорость, байт/с";
                xlWorkSheet.Cells[3, 2] = "Исходящие данные";
                // Выравнивание
                for (int i = 2; i < 4; i++) xlWorkSheet.Cells[2, i].HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlCenter;
                // Границы ячеек
                for (int i = 2; i < 5 + outMnt; i++)
                    for (int j = 2; j < 4; j++)
                        for (int k = 1; k < 5; k++)
                        {
                            if (i == 3 || i == 4 + outMnt) continue;
                            xlWorkSheet.Cells[i, j].Borders(k).ColorIndex = 1; // Границы слева, справа, сверху и снизу
                        }
                // Границы ячеек строка 3
                xlWorkSheet.Cells[3, 2].Borders(1).ColorIndex = 1; // Граница слева
                xlWorkSheet.Cells[3, 3].Borders(2).ColorIndex = 1; // Граница справа
                // Ширина столбцов
                Excel.Range range = xlWorkSheet.Range["B1:D1", System.Type.Missing];
                range.EntireColumn.ColumnWidth = 25;
                // Вывод исходящих данных
                for (int i = 0; i < outMnt; i++)
                {
                    xlWorkSheet.Cells[i + 4, 2] = arrsTimeSent[i];
                    xlWorkSheet.Cells[i + 4, 3] = Math.Round(arrSizeSent[i], 1);
                }
            }
            else
            {
                xlWorkSheet.Cells[count + 4, 2] = "Исходящие данные";
                // Выравнивание
                for (int i = 2; i < 4; i++) xlWorkSheet.Cells[2, i].HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlCenter;
                // Границы ячеек
                for (int i = 2; i < 5 + count + outMnt; i++)
                    for (int j = 2; j < 4; j++)
                        for (int k = 1; k < 5; k++)
                        {
                            if (i == 3 || i == 4 + count) continue;
                            xlWorkSheet.Cells[i, j].Borders(k).ColorIndex = 1; // Границы слева, справа, сверху и снизу
                        }
                // Границы ячеек
                xlWorkSheet.Cells[3, 2].Borders(1).ColorIndex = 1; // Граница слева
                xlWorkSheet.Cells[3, 3].Borders(2).ColorIndex = 1; // Граница справа
                xlWorkSheet.Cells[4 + count, 2].Borders(1).ColorIndex = 1; // Граница слева
                xlWorkSheet.Cells[4 + count, 3].Borders(2).ColorIndex = 1; // Граница справа
                // Ширина столбцов
                Excel.Range range = xlWorkSheet.Range["B1:D1", System.Type.Missing];
                range.EntireColumn.ColumnWidth = 25;
                // Вывод исходящих данных
                for (int i = 0; i < outMnt; i++)
                {
                    xlWorkSheet.Cells[i + count + 5, 2] = arrsTimeSent[i];
                    xlWorkSheet.Cells[i + count + 5, 3] = Math.Round(arrSizeSent[i], 1);
                }
            }
        }
    }
}

Приложение 2. Список имен категорий

Для вывода списка имен категорий употреблен следующий код:

Console.WriteLine("Category names");
foreach (System.Diagnostics.PerformanceCounterCategory c in System.Diagnostics.PerformanceCounterCategory.GetCategories())
{
Console.WriteLine(c.CategoryName);
}

Category names

Объект 'Задание'
Организация сети CLR .NET"
"Поставщик данных .NET для SqlServer
Общие ресурсы SMB-сервера
Прерыватель XHCI
WorkflowServiceHost 4.0.0.0
IPsec AuthIP IPv4
Сервер Teredo
IPsec AuthIP IPv6
WF (System.Workflow) 4.0.0.0
WAS_W3WP
ICMP
Службы терминалов
ASP.NET, версия v2.0.50727
MSDTC Bridge 3.0.0.0
Microsoft Winsock BSP
Активность сетевой карты для каждого процессора
ASP.NET v4.0.30319
UDPv6
Работа в сети CLR .NET 4.0.0.0
IPsec IKEv2 IPv6
Поток
Синхронизация
APP_POOL_WAS
Процесс
IPv4
IPv6
Процессор
WFPv4
Служба факсов
WFPv6
База данных ==> экземпляры
ServiceModelOperation 4.0.0.0
BitLocker
Удаленная работа с CLR .NET
Поставщик данных .NET для Oracle
ServiceModelService 3.0.0.0
Драйвер IPsec
Активность физической сетевой карты
Графика RemoteFX
ASP.NET Apps v4.0.30319
Телефония
База данных
ASP.NET
Индикатор питания
Логический диск
Всего RAS
Ретранслятор Teredo
Физический диск
Трассировка событий для Windows
Приложения ASP.NET
Подключения IPsec
ICMPv6
Память
Индексирование поиска
Подробно об объекте 'Задание'
Политика качества обслуживания сети
База данных ==> классы таблиц TableClasses
IKEv1, IKEv2 и AuthIP — универсальный
Безопасность CLR .NET
SMSvcHost 4.0.0.0
Компиляция по требованию (JIT) CLR .NET
Дисковые операции файловой системы
Трассировка событий для сеанса Windows
XHCI CommonBuffer
Сетевой адаптер
Глобальный IPHTTPS
DNS64 Global
Сеансы SMB-сервера
Память CLR .NET
WFP
Перенаправитель
ServiceModelOperation 3.0.0.0
Порт RAS
Диагностика производительности TCP/IP
Файл подкачки
ServiceModelEndpoint 4.0.0.0
Служба интеграции динамической памяти Hyper-V
Буфер передачи XHCI
Кэш записи дисковых пространств
Счетчики получения PacketDirect
Поток Pacer
Сетевой интерфейс
Подключение NBT
Браузер
TCPv6
Windows Workflow Foundation
Клиент Teredo
Фильтры получения PacketDirect
ServiceModelEndpoint 3.0.0.0
Таблица распределенной маршрутизации
Сведения о процессоре
TCPv4
Загрузка CLR .NET
Группу мелких объектов оптимизации доставки
Канал Pacer
Устройство RemoteFX Synth3D VSC VM
Использование PacketDirect EC
Глубина очереди PacketDirect
Память узлов NUMA
Сеанс IPHTTPS
Циклов работы для сети на ЦП/сек
CLR-данные .NET
Исключений CLR .NET
Система
Приложения ASP.NET, версия v2.0.50727
Данные термальной зоны
Сеть RemoteFX
ServiceModelService 4.0.0.0
USB
SMSvcHost 3.0.0.0
Объекты
IPsec IKEv1 IPv4
RAS
IPsec IKEv1 IPv6
Очередь печати
Уровень дисковых пространств
Счетчики передачи PacketDirect
Рабочий процесс PowerShell
Индикатор энергии
IPsec IKEv2 IPv4
Сетевой вход в систему
MSDTC Bridge 4.0.0.0
Кэш
Блокировки и потоки CLR .NET
Сервер SMB
Служба состояний ASP.NET
Взаимодействие CLR .NET
Протокол PNRP
Канал транспорта RemoteFX Synth3D VSC VM
UDPv4
Статистика квот WSMan
SynchronizationNuma

Список работ

Рейтинг@Mail.ru