Зачем нужен дамп и как его сделать

Знания и навыки требуемые для освоения материала:

  • Работа с командной строкой
  • Работа с архиватором (запаковать/ распаковать файл)

Для выявления причин сложных ошибок в программе TSLab может понадобится дамп памяти программы. Далее я расскажу в каких случаях он поможет и как его получить. Что такое дамп можно почитать здесь.

В начале небольшое введение, что из себя представляет код программы TSLab. Программа построена на управляемом коде и выполняется под управлением .NET Framework. Но для получения данных от брокера она взаимодействует с кодом провайдера данных, который в существующих вариантах (Transaq, SmartCom, Alor) выполнен в виде неуправляемого кода или машинного кода.

Если происходит ошибка в управляемом коде то она перехватывается внутри программы и, в зависимости от ошибки, errordlgили просто делается запись в лог-файл и продолжается выполнение программы или, для тяжелых ошибок, выводится диалог и программа аварийно завершается. В случае ошибки в неуправляемом коде .NET Framework в большинстве случаев перехватывает их превращает их в управляемое исключение, которое потом перехватывает программа. Но при определенных ошибках, как например

purevirtualcall

программа просто аварийно завершается без передачи управления в программу. В этом случае ни о какой записи в лог и речи не идет. В данном случае для выяснения причин где и из-за чего произошла ошибка поможет дамп.

Еще в одном случае он поможет в выяснении причины. Это в случае когда программа “зависает”, т.е. перестает реагировать на действия пользователя. В этом случае в логе программы тоже ничего не будет. Но здесь надо отличать зависание программы от замедленной реакции программы под нагрузкой. Такое поведение например получается когда на слабом компьютере запустить многопоточную оптимизацию и одновременно открыть много окон с быстроменяющимися инструментами.

Что делать в вышеперечисленных случаях? К сожалению по логам и тем более по скриншоту в данных ситуациях невозможно понять причину ошибки. Тут надо получать дамп и анализировать его. До недавнего времени считали что в таких случаях единственный вариант, это договариваться с пользователем о доступе на компьютер, т.к. получение дампа требовало установки специальных инструментов и умения работать с ними, что конечно нельзя предлагать обычным пользователям. В случае с паркингом это еще срабатывало, но в обычных случаях это проблематично.

Решение нашлось в виде относительно новой бесплатной программы ProcDump от известного автора Русиновича. Она позволяет создавать дамп при определенных условиях, которые задаются в командной строке. Давайте разберем что надо сделать для получения дампа в случаях зависания и краха программы. Предварительно надо установить на компьютер программу.

  • Скачать procdump.zip с http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx
    procdumpsite
  • Распаковать procdump.zip в какой-либо каталог, например c:\utils.
  • Открыть окно командной строки. Пуск -> Все программы -> Стандартные -> Командная строка.В случае работы под Vista или Windows 7 запускать надо от имени администратора. Для запуска с правами администратора, необходимо сделать следующее: Пуск — Все программы — Стандартные — Командная строка. Жмем правую клавишу и выбираем Запуск от имени администратора.
  • С командной строки перейти в папку где распакован procdumpcmdcd
  • Запустить программу procdump. При первом запуске она выводит окно с пользовательским соглашением, которое надо принять.Далее шаги для случая зависания и краха отличаются. Рассмотрим случай зависания, это более простой случай. В момент когда программа зависла надо запустить procdump со следующими параметрами:C:\utils>procdump -ma TSLabApp.exe crash.dmp
    После этого в текущей папке создастся файл crash.dmp.В случае с крахом(падением) программы все обстоит сложнее. В тот момент когда появился диалог об ошибке уже поздно что-то делать. В этот момент программа уже аварийно завершилась. Дальнейшие действия имеет смысл предпринимать только если подобная ошибка проявляется регулярно и в определенных ситуациях, например при выходе из программы после того как программа отработала весь день. В этом случае перед этим надо запустить программу procdump со следующими параметрами:
    C:\utils>procdump –e -w -ma TSLabApp.exe crash.dmpprocdump1
    Программа выполняется до тех пор пока не завершиться выполнение TSLabApp.exe, и в случае если она завершиться с ошибкой то создастся дамп.
  • Размер дампа варьируется от условий работы программы. Он хорошо сжимается, поэтому для пересылки его лучше запаковать, размер архива получится по крайней мере в два раза меньше исходного файла, и вложить его в сообщение на сайте поддержки http://support.tslab.ru/ с описанием ситуации.

Также есть еще один путь создания лога при падении программы, который работает на Windows 7. Для этого надо загрузить файл dump.reg (делается полный дамп) и кликнуть на нем. При этой операции требуются права администратора. Появится окно подтверждения, на котором надо ответить утвердительно.

После этого при падении программы TSLab в каталоге CrashDumps на диске с: будет создаваться дамп. В файле настроено, что максимально число дампов будет 2, далее новый дамп будет переписывать предыдущий. Более подробно можно почитать в msdn (на английском).

Дамп будет создаваться только при падении программы TSLab.

В дальнейшем, чтобы удалить данную функциональность, надо с помощью программы regedit удалить ветку реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps.

Создание пользовательского обработчика уведомлений для TSLab. Часть 2

В первой части я создал пользовательский обработчик, но он получился не настраиваемый, все настройки были заложены в код. Если понадобится изменить какой-либо параметр, например номер телефона, то обработчик потребуется пересобрать. В этой части я покажу как сделать обработчик настраиваемым.

Во-первым, создадим класс настроек нашего обработчика, содержащий все свойства, которые мы хотим, чтобы они были изменяемыми.

public class SmsNotifierSettings
    {
        public SmsNotifierSettings()
        {
            Login = "smser";        // логин клиента
            Password = "12345";
        }

        [LocalizeDisplayName("Логин")]
        public string Login { get; set; }

        [LocalizeDisplayName("Пароль")]
        public string Password { get; set; }

        [LocalizeDisplayName("Телефонный номер")]
        public string Number { get; set; }

        [LocalizeDisplayName("Использовать POST")]
        public bool UsePost { get; set; }

        [LocalizeDisplayName("Использовать HTTPS")]
        public bool UseHttps { get; set; }
    }

В конструкторе я задаю значения свойств по умолчанию, которые будут назначены при создании обработчика. Атрибут LocalizeDisplayName используется для задания локализованного имени свойства, которое будет выводится в окне настроек.

Теперь подключим этот класс в качестве класса настроек обработчика

private SmsNotifierSettings m_settings = new SmsNotifierSettings();

        ...

        public override object Settings
        {
            get { return m_settings; }
            set { m_settings = value as SmsNotifierSettings; }
        }

Здесь мы изменили переопределение свойства Settings по умолчанию, заданного в первоначальной версии обработчика. Далее надо все места коде, где использовались поля или константы, перешедшие в настройки,  перенаправить на на свойства класса настроек. Например

public override void Notify(NotifyEvent notifyEvent)
        {
            send_sms(m_settings.Number, notifyEvent.Message);
        }

 

            arg = "login=" + _urlencode(m_settings.Login) + "&psw=" + _urlencode(m_settings.Password) + "&fmt=1&" + arg;

            string url = (m_settings.UseHttps ? "https" : "http") + "://smsc.ru/sys/" + cmd + ".php" + (m_settings.UsePost ? "" : "?" + arg);

Компилируем и копируем в папку Notification. TSLab в этот момент надо закрыть, иначе операционная система не даст подменить файл. В любом случае до перезагрузки программы новый код не подхватится.

После запуска программы заходим в менеджер уведомлений, и видим, что у обработчика появилась кнопка Настройки и по ней появляется диалог настроек с нашими свойствами

img4

Все, теперь мы можем менять номер телефона прямо из программы и он будет сразу подхватываться.

Можно еще далее вносить какие-то улучшения в код для конкретных нужд, я остановлюсь на этом. Как вы убедились, для создания полноценного, причем полезного, обработчика потребовалось не так много кода.

SmsNotificationPlugin2.zip

Создание пользовательского обработчика уведомлений для TSLab. Часть 1

В TSLab, хотя это не отражено в документации, возможна установка дополнительных пользовательских обработчиков уведомлений. Я попробую восполнить этот пробел, на примере создания обработчика, посылающего SMS.

Для этого воспользуемся одним из онлайн-сервисов, позволяющих посылать SMS. Я выбрал http://smsc.ru , так как у него уже есть API для C# и примеры использования. Чтобы воспользоваться сервисом, необходимо в нем зарегистрироваться, причем, если указать номер телефона, то на счет добавят 15 рублей, что удобно для отладки. В секции API приводится исходный код библиотеки, но в оригинальном виде его неудобно использовать, так как там жестко прописаны логин и пароль, а также есть ссылки на классы HttpUtility и System.Windows.Forms.MessageBox, которые нам не нужны.

Я буду делать проект обработчика в среде Visual Studio 2012, но также возможно создание в SharpDevelop. Начинаем с создания нового проекта, выбирая в качестве шаблона Visual C# – Windows – Class Library. Не забудьте выставить версию .NET Framework не ниже 4.0.

Я назвал проект SmsNotificationPlugin. Сразу подключим необходимые библиотеки к проекту. Для этого в контекстном меню для папки References выбрать путь Add Reference и нажать внизу кнопку Browse. В окне выбора файлов надо перейти на каталог где установлен TSLab 1.2 и выбрать файлы TSLab.AddinsCommon.dll и TSLab.Utility.dll. Далее надо перейти на вкладку Assemblies – Framework и в списке выбрать System.ComponentModel.Composition.

img1

В результате список References должен выглядеть так

img2

Далее переходим непосредственно к созданию обработчика уведомлений. После создания в проекте создался класс Class1. Его можно переименовать или удалить и создать новый класс SmsNotifier. В начале файла добавляем ссылки

using TSLab.Addins.Notification;
using TSLab.Notification;

наследуем класс от NotificationHandler и реализуем требуемые методы. Получилась заготовка обработчика. Чтобы она “подхватилась” программой необходимо “подсветить” класс, указать атрибут NotificationHandlerAttribute . В результате заготовка обработчика выглядит так

using TSLab.Addins.Notification;
using TSLab.Notification;

namespace SmsNotificationPlugin
{
    [NotificationHandler(Name = "SMS", AllowMultiple = true)]
    public class SmsNotifier : NotificationHandler
    {
        public override void Notify(NotifyEvent notifyEvent)
        {
        }

        public override object Settings { get; set; }
    }
}

Параметр Name должен иметь уникальное имя среди всех подключенных обработчиков, параметр AllowMultiple указывает на то, что можно создавать больше одного экземпляра обработчика.

На данный момент это уже работоспособный обработчик. Если его подключить в программу, то, в зависимости от фильтров, в какие-то моменты будет вызываться метод Notify. Но так как он пустой, то никакой полезной работы он делать не будет. К свойству Settings перейдем попозже, пока, на первом этапе будем использовать жестко заданные параметры обработчика, такие как логин, пароль.

Давайте научим обработчик посылать SMS. Из взятого на сайте текста библиотеки я взял только нужное для посылки SMS. Во-первых это константы (потом превратим их в настраиваемые свойства)

// Константы с параметрами отправки
    const string SMSC_LOGIN = "<login>";        // логин клиента
    const string SMSC_PASSWORD = "<password>";    // пароль или MD5-хеш пароля в нижнем регистре
    const bool SMSC_POST = false;                // использовать метод POST
    const bool SMSC_HTTPS = false;                // использовать HTTPS протокол
    const string SMSC_CHARSET = "utf-8";        // кодировка сообщения (windows-1251 или koi8-r), по умолчанию используется utf-8

Вам необходимо прописать в константах SMSC_LOGIN и SMSC_PASSWORD свои логин/пароль, полученные при регистрации на сайте.

Во-вторых берем методы send_sms, _smsc_send_cmd и _urlencode с модификациями. В метод Notify добавляем вызов

            send_sms("79161234567", notifyEvent.Message);

где 79161234567 номер телефона, на который будет посылаться SMS, его нужно заменить на реальный номер. Собственно это весь код обработчика! Полностью весь код, с жестко прописанными константами выглядит так

using System;
using System.IO;
using System.Net;
using System.Text;
using TSLab.Addins.Notification;
using TSLab.Notification;
using TSLab.Utils;

namespace SmsNotificationPlugin
{

    [NotificationHandler(Name = "SMS", AllowMultiple = true)]
    public class SmsNotifier : NotificationHandler
    {
        // Константы с параметрами отправки
        const string SMSC_LOGIN = "<login>";        // логин клиента
        const string SMSC_PASSWORD = "<password>";    // пароль или MD5-хеш пароля в нижнем регистре
        const bool SMSC_POST = false;                // использовать метод POST
        const bool SMSC_HTTPS = false;                // использовать HTTPS протокол
        const string SMSC_CHARSET = "utf-8";        // кодировка сообщения (windows-1251 или koi8-r), по умолчанию используется utf-8

        public override void Notify(NotifyEvent notifyEvent)
        {
            send_sms("79161234567", notifyEvent.Message);
        }

        public override object Settings { get; set; }

        // Метод отправки SMS
        //
        // обязательные параметры:
        //
        // phones - список телефонов через запятую или точку с запятой
        // message - отправляемое сообщение
        //
        // необязательные параметры:
        //
        // translit - переводить или нет в транслит
        // time - необходимое время доставки в виде строки (DDMMYYhhmm, h1-h2, 0ts, +m)
        // id - идентификатор сообщения. Представляет собой 32-битное число в диапазоне от 1 до 2147483647.
        // format - формат сообщения (0 - обычное sms, 1 - flash-sms, 2 - wap-push, 3 - hlr, 4 - bin, 5 - bin-hex, 6 - ping-sms)
        // sender - имя отправителя (Sender ID). Для отключения Sender ID по умолчанию необходимо в качестве имени
        // передать пустую строку или точку.
        // query - строка дополнительных параметров, добавляемая в URL-запрос ("valid=01:00&maxsms=3")
        //
        // возвращает массив строк (<id>, <количество sms>, <стоимость>, <баланс>) в случае успешной отправки
        // либо массив строк (<id>, -<код ошибки>) в случае ошибки
        public string[] send_sms(string phones, string message, int translit = 0, string time = "", int id = 0, int format = 0, string sender = "", string query = "")
        {
            string[] formats = {"flash=1", "push=1", "hlr=1", "bin=1", "bin=2", "ping=1"};

            string[] m = _smsc_send_cmd("send", "cost=3&charset=" + SMSC_CHARSET + "&phones=" + _urlencode(phones)
                            + "&mes=" + _urlencode(message) + "&id=" + id.ToString() + "&translit=" + translit.ToString()
                            + (format > 0 ? "&" + formats[format-1] : "") + (sender != "" ? "&sender=" + _urlencode(sender) : "")
                            + (time != "" ? "&time=" + _urlencode(time) : "") + (query != "" ? "&" + query : ""));

            // (id, cnt, cost, balance) или (id, -error)

            return m;
        }

        // Метод вызова запроса. Формирует URL и делает 3 попытки чтения
        private string[] _smsc_send_cmd(string cmd, string arg)
        {
            arg = "login=" + _urlencode(SMSC_LOGIN) + "&psw=" + _urlencode(SMSC_PASSWORD) + "&fmt=1&" + arg;

            string url = (SMSC_HTTPS ? "https" : "http") + "://smsc.ru/sys/" + cmd + ".php" + (SMSC_POST ? "" : "?" + arg);

            WebRequest request = WebRequest.Create(url);
            StreamReader sr;

            if (SMSC_POST) {
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = arg.Length;
                Stream stream = request.GetRequestStream();
                stream.Write(Encoding.Default.GetBytes(arg), 0, arg.Length);
                stream.Close();
            }

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            string ret;
            int i = 0;

            do {
                if (i > 0)
                    System.Threading.Thread.Sleep(2000);

                sr = new StreamReader(response.GetResponseStream());
                ret = sr.ReadToEnd();
            }
            while (ret == "" && ++i < 3);

            if (ret == "") {
                    throw new Exception("Ошибка чтения адреса: " + url);

                ret = ","; // фиктивный ответ
            }

            return ret.Split(',');
        }

        // кодирование параметра в http-запросе
        private string _urlencode(string str)
        {
            return HttpUtils.UrlEncode(str);
        }
    }
}

Давайте проверим его в деле. После компиляции библиотеки получим файл SmsNotificationPlugin.dll. Далее его нужно поместить в нужный каталог, где его найдет TSLab. Перейдем в проводнике каталог данных программы TSLab. На Windows 7 это

c:\Users\<имя пользователя>\AppData\Local\TSLab\TSLab12

На него также можно выйти из TSLab, открым через меню папку логов и перейдя на уровень выше. В ней нужно создать папку Notification и скопировать туда наш файл обработчика SmsNotificationPlugin.dll. Теперь запускаем TSLab. Если программа уже запущена, то перезапускать не надо, обработчик подхватится “на лету”! Открываем окно Менеджера уведомлений и нажимаем кнопку Добавить. В списке доступных обработчиков должен появиться новый – SMS

img3

Добавим его и зададим ему фильтр “По номеру” с номером 1 – будет проходить уведомление при подключении любого поставщика данных. Также не забудем поставить галку в колонке Подключен. Попробуем подсоединиться любым поставщиком и при успешном подключении на телефон должна прийти SMS, например – “Вы подключились к поставщику данных  `Финам`”.

Все, у нас есть новый полезный обработчик! Но плохо что все данные установлены в коде и при изменении любого параметра, телефона например, необходимо перекомпилировать библиотеку. Давайте сделаем его “гибче”, чтобы параметры обработчика можно было устанавливать из программы TSLab.

SmsNotificationPlugin1.zip

Настройка сочетаний клавиш

В ночные сборки добавлена новая функциональность: Настройка сочетаний клавиш. Окно настройки вызывается из окна настроек программы.

Пока команды охватывают в основном Менеджер заявок, потому что сервис в первую очередь нужен скальперам, но в дальнейшем список команд будут расширяться.

Привет всем!

Добро пожаловать на блог TSLab!
В этом блоге мы постараемся рассказывать о новых возможностях программы TSLab.