Вторая жизнь DOS-приложений

Инженер-программист РУП "Витебское ПКБ АСУ" Пётр Кладов рассказывает о том, как удалось быстро и с минимальными затратами адаптировать DOS-приложения к современным требованиям

Время летит - и то, что ещё вчера было современным и актуальным, сегодня становится устаревшим, а завтра и вовсе отбрасывается. Казалось бы, ещё какой-то десяток лет назад операционная система MS-DOS и не думала уступать свои позиции, особенно в небольших организациях, не так часто приобретающих новую технику. Сегодня постепенно подрастает поколение компьютерщиков, не видевших "вживую" даже трёхдюймовую дискету. И хотя времена чёрного экрана DOS ушли безвозвратно и многим представляются сейчас каким-то каменным веком в истории вычислительной техники, люди жили и работали на компьютерах и в те времена. При этом именно тогда была создана масса программ, автоматизированных рабочих мест и систем управления, функциональность которых не утратила актуальности и по сей день. Так сложилось и в Витебском "ПКБ АСУ".


"Слабые места" MS-DOS

Большинство программ, разработанных специалистами "ПКБ АСУ", делалось ещё под MS-DOS. Они выверялись, тестировались и отлаживались годами, на них работали сотни и тысячи людей. Но неумолимый технический прогресс всегда таит в себе подводные камни: в современных версиях Windows и на оборудовании с нынешней конфигурацией DOS-приложения не всегда получают полноценную функциональность. "Больным местом" в их работе является, например, вывод на печать, особенно на USB-принтеры. Утилиты вроде DOSPRN лишь отчасти помогают решить эту проблему.

Другим "узким" местом DOS-приложений, как ни странно, можно считать саму MS-DOS, вернее, её ограниченную оперативную память. Для небольших программ она практически не играет роли, однако в объёмных проектах может стать серьёзным ограничением для размера баз данных, которыми можно оперировать в реальном времени. Это, в свою очередь, вызывает ограничения размера справочников, количества полей в таблицах и т.д. Различные же манипуляции с дисковой памятью приводят к существенному снижению быстродействия. Средства для работы с расширенной памятью компьютера из MS-DOS тоже не всегда выручают, особенно если их применение изначально не планировалось, а потолок оперативной памяти достигнут только в ходе расширения функциональности приложения.


"Пугающий" интерфейс

Что же можно сделать в таком случае? Само собой, интуитивно напрашивается естественное решение: переписать все актуальные программы под Windows. Но у такого подхода есть ряд серьёзных недостатков. Во-первых, на новую разработку всех приложений требуются большие средства. Некоторые наши программы имеют десятки и даже сотни тысяч строк кода, сотни выходных форм, десятки справочников, множество сервисных систем и модулей обработки данных. Они создавались, отлаживались, тестировались и совершенствовались длительное время, и так просто взять и переписать их, затем тестировать и отлаживать новый софт - сложная и объёмная задача. Во-вторых, новое приложение в новой операционной системе ведёт к появлению нового интерфейса взамен старого, привычного для пользователей. И эта, вторая проблема, на самом деле, имеет достаточно серьёзные последствия: она означает необходимость переучиваться, фактически заново изучать знакомые операции. А когда речь идёт о программе, имеющей сотни различных экранов для ввода, сервиса, обработки информации, формирования выходных данных и т.п., - задача становится достаточно серьёзной и способна надолго остановить или затормозить работу предприятия. Немало существует реальных примеров того, как организации просто отказывались переходить на новую версию программы только из-за её нового интерфейса. Конечно, есть ситуации, когда такой переход просто необходим, и без него физически не обойтись, но это всегда очень трудно. Как показывает практика, если выигрыш в функциональности сравнительно невелик, вряд ли кто-то захочет так просто внедрять новую программу, зная, какие проблемы его при этом ожидают.


Даёшь консольные приложения!

И всё же проблему, казалось бы, неразрешимую, удалось снять очень просто, убив сразу двух зайцев: преодолев все ограничения и сохранив старый интерфейс с минимумом затрат и побочных эффектов. Летом 2007 года нами была разработана технология, позволяющая с использованием среды Borland Delphi перекомпилировать DOS-приложения, написанные в среде Borland Pascal, в Windows-приложения.

Идея этого метода проста: обе среды используют в своей основе один и тот же язык программирования: Pascal (имеющиеся различия пока не в счёт). Соответственно, теоретически возможно создать программу, исходные тексты которой в равной мере компилировалась бы в обеих средах. У неискушённого читателя может возникнуть недоумение: что общего между программами, создаваемыми в Borland Pascal, работающими в текстовом режиме MS-DOS, и оконными приложениями Windows, создаваемыми в Delphi; как можно на одних исходных кодах создать и то, и другое? Ответ на этот вопрос абсолютно прост: консольные приложения Windows.

Это полноценные Windows-приложения, обладающие текстовым интерфейсом (тем самым, который используется в MS-DOS), но при этом имеющие доступ ко всем возможностям операционной системы Windows, даже, как это ни странно звучит, к её стандартному графическому интерфейсу. Создание консольного приложения в Delphi изначально не слишком отличается от создания такового в Borland Pascal. В головном файле нового проекта необходимо указать директиву {$APPTYPE CONSOLE}, чтобы обозначить, что мы создаём консольное приложение. И далее можно смело убирать секцию Uses со всем содержимым. Простейшее консольное приложение будет выглядеть так:

Program Hello;
{$APPTYPE CONSOLE}
Begin
 WriteLn('Hello, world!');
 ReadLn
End.

Да-да, в результате компиляции данного кода в Delphi мы получим полноценное Windows-приложение. Скопируйте этот же код в Borland Pascal и попробуйте скомпилировать его там. Сразу это сделать не удастся - компилятор сообщит об ошибке 17: "Неверная директива компилятора", ведь в Borland Pascal нет директивы $APPTYPE. Однако стоит её убрать, и вы сразу скомпилируете приложение под MS-DOS.

Итак, мы получили два исполнимых файла с абсолютно одинаковой функциональностью, но предназначенные для различных операционных систем. Единственное, чего мы пока не добились, - это единство исходного кода. Замечательным решением этой проблемы является использование блоков условной компиляции. Подробную информацию о них и об их использовании можно получить в справке Delphi, мы же сейчас обратим внимание на то, что в Delphi, в отличие от Borland Pascal, присутствует условная константа MSWINDOWS. Вот её мы и будем использовать для разграничения участков кода, предназначенного только для компилятора Delphi или только для компилятора Borland Pascal. Собственно, программа теперь изменится на следующую:

Program Hello;
{$IFDEF MSWINDOWS}
 {$APPTYPE CONSOLE}
{$ENDIF}
Begin
 WriteLn('Hello, world!');
 ReadLn
End.

Что поменялось? Директива {$APPTYPE CONSOLE} будет задействована только при компиляции в Delphi, Borland Pascal её проигнорирует.

Теперь у нас осталось последнее препятствие: головной файл проекта в Delphi имеет расширение dpr, в то время как Borland Pascal работает только с файлами pas. Здесь всё ещё проще: сохраняем приведённый выше текст программы в файле с расширением pas, например, hello.pas, а затем создаём файл с расширением dpr (hello.dpr) и помещаем в него единственную строчку: {$I hello.pas}. Таким образом, компилятор Delphi в качестве содержимого файла hello.dpr будет воспринимать содержимое файла hello.pas. Между прочим, в таком случае директиву {$APPTYPE CONSOLE} можно просто вставить в начало dpr-файла, вообще не используя блок условной компиляции.

Отдельного разговора заслуживают модули Borland Pascal, отсутствующие в Delphi, в частности, модуль CRT. Его придётся переписать самостоятельно (либо найти готовое решение, платное или бесплатное, в Интернете), используя стандартные функции Windows API для работы с консолью. Они находятся в модуле Windows, исчерпывающий справочный материал по их использованию можно найти в Microsoft Win32 Programmer's Reference, входящем в состав справочной системы Delphi, в разделе "Consoles and Character-Mode Support".

Модуль DOS при помощи блока условной компиляции можно заменить стандартным модулем SysUtils, имеющим в себе практически те же функции, процедуры и переменные. В основном, изменились только их названия: например, тип SearchRec получил название TSearchRec, константы атрибутов файла получили в начале имени буквы fa (AnyFile стала faAnyFile). Проблему совместимости можно решить также при помощи блоков условной компиляции, допустим, определив в Delphi тип SearchRec, равный типу TSearchRec.

Что касается печати, то для ассоциирования файловой переменной lst с принтером в Delphi используется процедура AssignPrn(lst), далее изначально печать осуществляется так же, как и в DOS. Однако можно использовать все возможности, доступные любому приложению в Windows: печать любого текста и графики, использование очереди печати, использование любого принтера, установленного в системе, и т.д. Как именно это делается, описано в любом справочнике по Delphi (модуль Printer).

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

Application.CreateForm(TForm1, Form1);
Form1.ShowModal;
Form1.Hide;
Form1.Free;
While KeyPressed do ReadKey;

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


"Подводные камни"

Разумеется, без них не обходится ни один проект. Одним таким камнем при написании подобных приложений является то, что при работе с консолью в Windows используется ASCII. В этой кодировке должны быть представлены все константы, выводимые на экран в консоли, в этой же кодировке вводятся символы с клавиатуры. Разумеется, это относится только к текстовому окну: при работе с формами используется обычная кодировка Windows. И хотя подобный "анахронизм" является, скорее, плюсом при работе со старыми DOS-приложениями, об использовании различных кодировок в текстовом окне и в формах следует помнить при отображении, скажем, данных, введённых в форму, в консоли.

Другой подводный камень - это формат данных, что важно при записи и чтении с диска. Например, тип Integer в Delphi соответствует типу LongInt в Borland Pascal. Однако в Delphi имеется как раз подходящий по описанию тип SmallInt. Или, например, тип Real в Borland Pascal имеет длину 6 бит, а в Delphi - 8. Однако можно перейти к 6-битному типу Real при помощи директивы компилятора {$REALCOMPATIBILITY ON}.


Только Delphi!

Возможно, кто-то захочет задать вопрос: "Почему использовался Delphi, если есть Free Pascal, с помощью которого можно было бы сделать то же самое?" Действительно, почему? Всё дело в том, что мы, собственно, с Free Pascal и начали. И в результате полутора месяцев проб и экспериментов окончательно его отвергли из-за нестабильности среды и выявленных проблем, хотя она и значилась как стабильная рабочая версия. Возникшие ошибки и проблемы были довольно разнообразными: то самопроизвольно менялись настройки среды в процессе работы программы, то неожиданно начинали возникать ошибки на ровном месте, то компилятор неожиданно "терял желание" адекватно воспринимать некоторые вполне нормальные участки кода. После перезапуска среды некоторые проблемы исчезали, потом спонтанно появлялись вновь или вместо них возникали новые ошибки и сбои. В общем, результаты показали, что эта среда достаточно нестабильна, и даже если ошибки будут устраняться разработчиками, не факт, что впоследствии не появятся новые или не будут обнаружены другие. Заниматься доводкой чужой среды, тратить на это время, деньги и силы нет смысла по причине нерациональности. С Delphi же мы работаем уже много лет, это привычная для нас надёжная и стабильная среда. Кроме того, в ней, теоретически, имеется возможность создания "тройных" приложений DOS/Windows/Linux с единым исходным кодом при использовании среды Borland Kylix, однако пока в подобных разработках не было необходимости.


Зарплата и учёт

В нашем же ПКБ первой программой, на которой была испытана технология, стал программный комплекс бухгалтера "Зарплата". Экономический эффект превзошёл все ожидания: программа содержит в себе около сотни выходных форм, имеет широкие функциональные возможности, а её исходные коды содержат более 110 000 строк. По предварительным и самым скромным оценкам, на написание новой версии понадобилось бы три человеко-года. На создание же единой DOS/Windows-версии с общими исходными кодами потребовалось полтора человеко-месяца, кроме того, около года ушло на бета-тестирование. В результате, например, максимальное число работающих увеличилось с 2500 до 25 000 человек. Причём новое ограничение подобрано чисто эмпирически: при необходимости его можно поднять хоть до 25 000 000, пока не будет исчерпан верхний предел памяти, выделяемой программе в Win32: 2 Гб. Решены многие проблемы с печатью: как было упомянуто выше, теперь можно выводить данные на любой установленный в системе принтер без программ-посредников. В качестве эксперимента был введён дополнительный текстовый редактор, использующий GUI (поль-зователю дана возможность выбора между новым редактором и традиционным консольным). Одним из главных достижений является то, что обе версии, под DOS и под Windows, работают с одной и той же базой данных. (Я не имею в виду случай, когда база по максимальному числу записей увеличена под Windows-версию и приложение DOS не видит "лишние" записи и не может считать их в память.)

Первый опыт подобного перевода был обобщён и реализован в программе "Учёт заготовки льна", предназначенной для льнозаводов. На её перевод было затрачено примерно три человеко-недели, причём за это самое время была полностью переписана система вывода на печать. По результатам тестирования этой программы после перевода можно сказать, что нам удалось в достаточной мере отработать описанную технологию и добиться минимального числа ошибок. На момент написания статьи при эксплуатации бета-версии АРМ "Учёт заготовки льна" была выявлена всего одна, устранённая спустя полчаса.

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

Эдуард ТРОШИН,
Пётр КЛАДОВ


Прошлый материал о разработках витебского ПКБ АСУ был опубликован в статье "Под DOS для... глубинки" ("КВ" №
35'2003). Уже тогда эта тема вызвала живой отклик читателей. Позволим себе процитировать некоторые комментарии посетителей нашего форума.

Мне кажется, главное - не интерфейс (UI) в программах, а эффективность работы. Возьмите, к примеру, программу STATGRAPHIC. Что она, хуже Windows-аналогов?

Роман Карпач


Почему нельзя сочетать и UI, и функциональность? Причём, если сам не хочешь писать UI - дай возможность это сделать другим.

Взять, к примеру, CVS - нормальный продукт по функциональности, хотя и модернизация ему не помешает. Там ведь невозможно прикрутить никакой другой UI, кроме command-line, все WinCVS-ы - всего лишь обёртка вокруг командной строки, что не оставляет никаких шансов интегрировать его, скажем, в некую IDE. Почему помойный SourceSafe это умеет, а крутой CVS - нет?

Патологоанатом


Ну и что? Таких контор в Минске тьма-тьмущая. Сейчас начнём про каждую писать, да? Насчёт DOS-окон. У нас крутятся задачи, которые были разработаны ещё для машин класса CM ЭВМ, которые плавно мигрировали вместе с базами на PC. При этом процент переделки при миграции составил всего 10%. C точки зрения железа, переключили терминалы с СМ на РС, притом на 386 поддержка была до 32 удалённых терминальных рабочих мест. С приходом Windows, Linux мигрировали те же задачи и базы и на эти платформы. И всё успешно функционирует. Пример: МГТС, более 100 удалённых терминальных рабочих мест на двух серверах PC класса XEON, работающих по протоколам RS232, LAT и Telnet; Минский завод "Кристалл" - более 50 удалённых рабочих мест по протоколу Telnet, работающих на одном сервере PC класса P4 под Windows 2000. В качестве рабочей telnet-станции может быть 286 компьютер с установленной сетевой платой.

Т.к. изначально (более десяти лет назад) была удачно выбрана многопользовательская, многозадачная СУБД, то все задачи до сих пор успешно работают с переходом с одной платформы на другую. Не тратятся каждый раз впустую деньги на разработку ПО с нуля. На сегодня данная СУБД выступает под именем Cache (объектно-ориентированая многомерная база данных) и успешно развивается как у нас в Беларуси, так и во всём мире.

alex


Да уж... Народ пытается изобретать велосипед с нуля, то есть с изобретения колеса. :)

А чего мудрить-то? Есть вышеупомянутый STATGRAPHIC. Если порыться, можно найти досовые версии Paradox или FoxPro. Разумеется, они платные (эти жмоты не снимают лицензию даже на откровенное abandonware). Но открою страшную тайну - оболочка connect умеет просматривать и редактировать файлы dbf (создать их, правда, придётся вручную).

суслик (эникейщик)


Пользователю на заводе "Гомсельмаш" всё равно, под какой операционной системой работает приложение. Он работает не с операционной системой, а с программой. Вообще под DOS даже лучше, нет многозадачности и они не будут отвлекаться на игру в Lines.

Антон

Версия для печатиВерсия для печати

Номер: 

37 за 2008 год

Рубрика: 

На заметку
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!