Как перестать беспокоиться и начать программировать


Пора копнуть поглубже…


Для начала хорошая новость: хочется надеяться, что Borland всё-таки не окончательно "кинула" разработчиков на C++ Builder . Кажется, теперь Delphi и C++ Builder сольются, наконец, в экстазе.

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

Приступаю к описанию системных компонентов с закладки "ASK Tools". В первой статье я агитировал за то, что обработка любых ошибок и нештатных ситуаций времени исполнения должна быть единообразной и должна использовать только механизм исключений (Exceptions). Все выгоды такой унификации описаны там же.

Исходим из предположения, что мы проделали большую работу по обёртке всех C и API-вызовов в свои классы с "исключительной" обработкой ошибок. Теперь программа не "валится" без объяснений в нештатной ситуации. Пришло время, наконец, снять сливки с наших трудов.

Как всегда, хочется большего: чтобы все проблемы, возникающие во время выполнения программы, протоколировались. Протокол должен быть содержательным в той мере, которая поможет разработчику устранить проблему. Ещё надо бы иметь средство визуализации протокола сбоев. Ну и, конечно, хотелось бы, чтобы для включения этой замечательной функциональности в каждом новом проекте, не пришлось напрягаться.

Общий план реализации таков. Компонент TAskExceptionHandler "бросается" на главную форму приложения. На этом, собственно, "ручное кодирование" заканчивается. Компонент перехватывает все исключения и "вываливает" их в лог-файл, после чего исключение обрабатывается стандартным образом. Если вам понадобится раскрыть более полно информацию об исключении особо хитрого типа, вы всегда сможете включить обработку этого типа в метод LogExceptionState.

В момент возникновения исключений делается "снимок состояния" системы, который также регистрируется в лог-файле вместе с событием. Лог-файл имеет структуру ini-файла и имя, сформированное по имени приложения.
Образец прилагается.

[12.11.2004 16:06:47] ExceptionType=EToFile ExceptionMess=Ошибка записи в файл ToFileFileName=A:\big_file.txt ToFileErrNo=28 ToFileDosErrNo=112 ToFileErrNoStr=Недостаточно места на устройстве ToFileDosErrNoStr= not enough space on the disk ClassName=FormOptions (TFormOptions) FormName=FormOptions (TFormOptions) ProgramVersion=1.0.0.0 TotalVirtMem=2047 AvailVirtMem=2000 TotalPageMem=1228 AvailPageMem=895 DiskC_Total=76316 DiskC_Free=41916

Компонент, естественно, использует классы из упоминавшейся библиотеки классов (IniFile, ToFile), а также некоторые компоненты, речь о которых пойдёт ниже. Также используются файлы текстовых ресурсов – для формирования сообщений на языке пользователя.

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

void CreateVeryBigFile() {

ToFile w("w", "A:\\big_file.txt");

while(1) w.fprintf("Очень-очень большой файл…\n");

}

Результат работы "перехватчика исключений" можно рассмотреть с помощью стандартной . Библиотека форм общего назначения также является ресурсом и представляет собою отдельную DLL, которая будет описана в последующих статьях.

Как уже говорилось, благодаря такой организации обработки ошибок, программы не "валятся" без объяснений причин. Протокол работы помогает выявить и устранить многие проблемы времени выполнения. Более того, можно организовать отсылку протоколов разработчику – через e-mail или FTP – для удалённой диагностики проблем и выпусков патчей.

Кстати, перехват ошибок файловой системы весьма помогает при работе с устаревшими Windows 9x, в которых часто возникают сбои в FAT.

TAskExceptionHandler использует несколько компонентов с закладки "ASK SysInfo", на которую мы плавно переместимся. Знакомьтесь: TAskOS.


Не секрет, что в процессе разработки программ часто бывает необходимо определить версию Windows, под управлением которой выполняется программа. На разных форумах довольно много подобных вопросов от новичков. Свойства компонента:

  • enumOSType Type – Тип ОС. Может принимать значения: otUnknown, WIN_95, WIN_98, WIN_ME, WIN_NT, WIN_2000, WIN_XP, WIN_2003, WIN_LATEST


  • AnsiString OSName – строковое наименование ОС


  • enumOSPlatform Platform – тип платформы Windows; может принимать значения: opUnknown, _9x, NT


  • AnsiString Version – версия Windows


  • AnsiString WinDir – папка, в которую установлена Windows


  • AnsiString WinSetupDir – папка, из которой установлена Windows


  • AnsiString WinSysDir – системная папка (%WinDir%\SYSTEM для Windows 9x/ME и %WinDir%\SYSTEM32 для Windows NT/2000/XP/2003 etc.)


  • AnsiString TempPath – папка для временных файлов


  • AnsiString WinLang – строковое обозначение языка локализации Windows


  • bool Plus – индикатор, установлен ли пакет Plus! Для Windows 9x


  • enumWinRole Role – Роль Windows. Может принимать значения: wrUnknown, wrServer, wrWorkstation. Критики, минуточку внимания! Я знаю, что можно расширить и углубить значения этого свойства, но указанных значений для моих целей достаточно. Кому не хватает – напрягутся сами.


  • AnsiString AppData – полный путь к папке "\Documents and Settings\\Application Data"


  • AnsiString LocalSettings – полный путь к папке "\Documents and Settings\\Local Settings"


  • AnsiString LocalAppData – полный путь к папке "\Documents and Settings\\Local Settings\Application Data"


  • Компонент TAskOS, как и все остальные с этой закладки, имеет метод Refresh(), который вызывается автоматически, если компонент лежит на форме. То есть, после создания формы все свойства компонента уже содержат правильные значения и готовы к использованию. А вот если компонент создаётся динамически в куче, следует вызвать этот метод вручную для инициализации свойств.

    Также многие компоненты имеют свойство bRefresh. Если этому свойству во время проектирования присвоить значение "true", то будет вызван метод Refresh и значения свойств можно будет увидеть в инспекторе объектов.



    Компонент TAskComputer инкапсулирует следующие свойства:

  • AnsiString ComputerName – имя компьютера


  • AnsiString UserName – имя пользователя


  • long RAM – объём оперативной памяти


  • long RAMUsage – объём используемой памяти. Вычисляется динамически, в момент чтения значения свойства


  • Компонент TAskProcessor имеет следующие полезные свойства:

  • AnsiString CPUName – наименование процессора


  • AnsiString CPUIdentifier – идентификатор процессора


  • long Frequency – Частота процессора


  • double Usage – Процент использования процессора. Вычисляется динамически, в момент чтения значения свойства


  • Компонент TAskDisplay.

  • short Width – текущая ширина экрана в пикселях


  • short Height - текущая высота экрана в пикселях


  • __int64 ColorsCount – глубина цвета


  • short ColorsBits - глубина цвета в битах


  • TStringList * ListModes – список поддерживаемых режимов


  • AnsiString CardName – наименование видеокарты


  • short RefreshRate – частота обновления


  • AnsiString DisplayName – наименование монитора


  • Компонент TAskKeyboard.

  • bool NumLock – индикатор и манипулятор клавиши "NumLock". Метод Read возвращает состояние кнопки; метод Write устанавливает кнопку в соответствующее состояние (включает/выключает NumLock)


  • bool CapsLock – индикатор и манипулятор клавиши "CapsLock"


  • int LangsCount – количество установленных в системе языков локализации


  • AnsiString LangName – текущий язык локализации Windows (например, "Русский")


  • AnsiString LangCode3 – трёхбуквенное обозначение текущей раскладки (например, "RUS")


  • AnsiString LangCode2 - двухбуквенное обозначение текущей раскладки (например, "RU")


  • Именно с помощью этого компонента выставляются клавиатурные свойства у компонентов TAskEdit, TAskMaskEdit, TAskRxCalcEdit, TAskCurrencyEdit, TAskComboBox, TAskMemo из предыдущей статьи.

    Компонент TAskPrinter. Я не настаиваю на общественной полезности этого компонента; просто в последующих статьях он будет упоминаться, поэтому он и описан здесь.

  • AnsiString DefPrinter – принтер по умолчанию




  • AnsiString CurPrinter – текущий принтер


  • AskPrinterSystem PrintSystem – система печати; может принимать значения: apsMatrix, apsLaser, apsStream, apsOther, apsUnknown=666


  • TStringList * Printers – список установленных в системе принтеров


  • int ItemIndex – индекс текущего принтера


  • AnsiString PaperFeed – управляющий символ "прогон листа" - различается для принтеров разных систем печати (матричный, лазерный)


  • Основные функции.

  • Во-первых, компонент пытается (не всегда удачно) определить тип принтера: матричный, лазерный, струйный, и т.п. Вообще, лучше бы ему указать это явно.


  • Во-вторых, компонент печатает любой текст методом PrintStringList(), причём делает это крайне разумно: текст печатается в текстовом (не графическом) режиме, что обеспечивает высокую скорость печати на матричных принтерах. Это есть хорошо для бюджетных контор, которые осознают, что стоимость владения и эксплуатации матричного принтера намного меньше, чем лазерного.


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


  • Компонент TAskDisk предоставляет наиболее употребимую информацию о логических дисках.

  • AnsiString Letter – буква диска. При присвоении значения этому свойству выполняется метод Refresh() для соответствующего диска


  • AnsiString SerialNum – серийный номер


  • enumDiskType Type - тип диска; может принимать значения: dtUnknown, dtNOTROOTDIR, dtREMOVABLE, dtFIXED, dtREMOTE, dtCDROM, dtRAMDISK


  • AnsiString Label – метка диска


  • AnsiString FileSystem – файловая система


  • __int64 Size – размер диска в байтах


  • __int64 Free – размер свободного места


  • bool DiskInDrive – признак, вставлен ли съёмный диск в устройство; обращение к этому свойству не вызывает неубираемого системного окошка типа "Нет диска в дисководе"


  • AnsiString sType – тип диска на языке локализации Windows (например, "Сменный", "Локальный", "CD-ROM", и т.д.).


    Здесь используется файл строковых ресурсов, о котором говорилось в первой статье.


  • Компонент TAskListDisks содержит список всех логических дисков.

  • int Count – количество дисков


  • AnsiString List – список дисков


  • TAskDisk * Disk – указатель на компонент, могущий полноценно описать выбранный диск


  • Компонент TAskCard – описание карты (платы).

  • enumCardType Type – тип карты; может принимать значения: ctNetwork, ctSound, ctVideo, ctSCSI


  • AnsiString CardName – наименование карты


  • AnsiString MACAddr – MAC адрес сетевой карты


  • AnsiString IPAddress – IP адрес сетевой карты


  • Компонент TAskShutdown несколько выбивается из ряда компонентов, предоставляющих информацию о системе. Он предназначен для удобного "гашения" Windows и обладает следующими свойствами:

  • ShutdownType Type – тип "гашения"; может принимать значения: ewxLOGOFF, ewxPOWEROFF, ewxREBOOT, ewxSHUTDOWN


  • bool Force – признак "ускоренного гашения" - без ожидания ответа на вопросы, закрывать ли то или иное приложение


  • Метод DoIt() выполнит поставленную задачу (заданную описанными свойствами).


  • Ну, и на сладкое – компонент TAskSysInfo, являющийся контейнером компонентов: TAskOS * OS, TAskCPU * CPU, TAskListDisks * ListDisks, TAskComputer * Computer, TAskKeyboard * Keyboard, TAskDisplay * Display, TAskCard * NetworkCard, TAskCard * SoundCard, TAskCard * SCSICard.

    Помимо этого, компонент обладает следующими свойствами:

  • bool ActiveOnLoaded – указывает, начинать ли тестирование системы сразу же, как появляется форма, на которой лежит компонент. Может случиться, что это надо сделать не сразу, а немного погодя. В таком случае вызовите метод Refresh() вручную.


  • TStringList * Printers – список установленных принтеров


  • TStringList * Resources – список ресурсов, отданных "в общее пользование"


  • TStringList * SoftList – список установленного в системе софта. Кроме того, в массиве TMapSoft содержится следующая информация о каждом установленном продукте:


  • Версия


  • Производитель


  • URL продукта или производителя




  • ID продукта


  • На кого зарегистрирован


  • Компания, в которой работает товарищ, на которого зарегистрирован продукт


  • Кроме того, у компонента TAskSysInfo есть 2 события:

  • OnEndRefresh – возникает по окончании "нарывания" общесистемной информации; в общем случае это событие возникает раньше, чем OnEndRefreshDisks


  • OnEndRefreshDisks - возникает по окончании "нарывания" информации о логических дисках


  • Результат работы компонента во время проектирования представлен на рисунках , , , , , .

    Результат работы компонента во время выполнения представлен на рисунке , которая также лежит в DLL форм общего назначения. Подключение этой и любых других DLL к любому проекту осуществляется двумя кликами мышки с помощью методов, описанных в грядущем продолжении цикла статей.

    Скачать архив (35K)

    1






  • Содержание  Назад  Вперед