Пора копнуть поглубже…
Для начала хорошая новость: хочется надеяться, что 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
Все публикации раздела