Главная Рефераты по рекламе Рефераты по физике Рефераты по философии Рефераты по финансам Рефераты по химии Рефераты по хозяйственному праву Рефераты по цифровым устройствам Рефераты по экологическому праву Рефераты по экономико-математическому моделированию Рефераты по экономической географии Рефераты по экономической теории Рефераты по этике Рефераты по юриспруденции Рефераты по языковедению Рефераты по юридическим наукам Рефераты по истории Рефераты по компьютерным наукам Рефераты по медицинским наукам Рефераты по финансовым наукам Рефераты по управленческим наукам Психология и педагогика Промышленность производство Биология и химия Языкознание филология Издательское дело и полиграфия Рефераты по краеведению и этнографии Рефераты по религии и мифологии Рефераты по медицине Рефераты по сексологии Рефераты по информатике программированию Краткое содержание произведений |
Курсовая работа: Разработка вспомогательной системной программы в системе программирования Delphi с использованием средств WinApiКурсовая работа: Разработка вспомогательной системной программы в системе программирования Delphi с использованием средств WinApiМинистерство образования и науки Российской Федерации Государственное образовательное учреждение высшего профессионального образования РЯЗАНСКИЙ ГОСУДАРСТВЕННЫЙ РАДИОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ Кафедра ЭВМ ПОЯСНИТЕЛЬНАЯ ЗАПИСКА К КУРСОВОЙ РАБОТЕ по дисциплине “Операционные системы” по теме “Разработка вспомогательной системной программы в системе программирования Delphi с использованием средств WinApi” Выполнил студент группы 742 Шипилов Д.А. Руководитель Доц. Каф. ЭВМ Засорин С.В.
Рязань 2010 Содержание Введение 1. Техническое задание 1.1 Основания для разработки программы 1.2 Назначение разработки 1.3 Требования к программам 1.4 Требования к надежности 1.5 Требования к программной документации 1.6 Текст задания по варианту 2. Описания разработанных программ 2.1 Общие сведения 2.2 Функциональное назначение 2.3 Описание логической структуры 2.3.1 Логическая структура программы 2.3.2 Логическая структура справочной системы 2.3.3 Создание программы-инсталлятора 2.4 Используемые технические средства 2.5 Вызов и загрузка 2.6 Входные данные 2.7 Выходные данные 3. Программа и методика испытаний 3.1 Объект испытаний 3.2 Цель испытаний 3.3 Требования к программе 3.4 Требования к программной документации 3.5 Средства и порядок испытаний 3.6 Методы испытаний 3.6.1 Тестирование программы методом белого ящика 3.6.2 Тестирование программы методом чёрного ящика 4. Эксплуатационные документы 4.1 Руководство программиста 4.1.1 Общие сведения о программе 4.1.2 Структура программ 4.1.3 Проверка программ 4.1.4 Дополнительные возможности 4.1.5 Сообщения системному программисту 4.2. Руководство оператора (пользователя) 4.2.1 Назначение и условия применения программ 4.2.2 Обращение к программам для запуска 4.2.3 Входные и выходные данные 4.2.4 Сообщения оператору Приложение Список литературы В данной курсовой работе было разработано приложение осуществляющее передачу данных между копиями этого приложения с помощью потоков, а также анализ системной области рабочего. Анализ производится путём ассоциирования жёсткого диска с файлом программы и дальнейшей работы с дескриптором этого файла. 1.1 Основания для разработки программыОснованием для разработки программы являлось задание для курсового проекта (вариант 21). Содержание задания: Разработать многопоточное приложение, выполняющее различные операции: 1)Обмен данными между двумя процессами с помощью файла проецируемого в память. 2)Анализ содержимого служебной области системного диска. 1.2 Назначение разработкиПрограмма служит для обмена текстовыми сообщениями между копиями этой программы, а также для анализа активных носителей, присутствующих в системе. Конкретно, происходит анализ блока параметров BIOS выбранного логического диска на носителе, и считывание и анализ таблицы разделов этого носителя. 1.3 Требования к программамПриложение должно удовлетворять следующим требованиям: 1) Обеспечивать указание данных для обмена в одном из процессов 2) Выполнять чтение и анализ содержимого служебной области, расшифровку её содержимого и представление результатов в виде таблицы на устройство стандартного вывода или в файле. В данном приложении реализован способ представления результатов работы в устройстве стандартного вывода информации - мониторе. Для удобства модификации приложения оно выполнено в виде нескольких функциональных модулей. Первая группа модулей служит для обмена данными между различными копиями приложения. Вторая группа модулей служит для считывания рабочей области системного, или какого-либо другого носителя информации. Приложение позволяет получить информацию о таблице разделов физического носителя и блоке параметров BIOS этого носителя. 1.4 Требования к надежностиПрограмма должна выдавать сообщения об ошибках в следующих случаях: 1)Если не удалось создать проекцию файла 2)Не удалось синхронизировать приложение с другими копиями приложения 3)Не удалось осуществить обмен данными 4) Если не введено имя при регистрации пользователя в системе 1.5 Требования к программной документацииПриложение должно содержать справочную систему , включающую в себя всю необходимую информацию по работе программы. 1.6 Текст задания по вариантуРазработать многопоточное приложение, выполняющее операции. 1)Обмен данными между двумя процессами с помощью файлов проецируемых в память. 2)Анализ содержимого служебной области системного диска. Исходные данные: Для выполнения первой операции использовать прикладные программы типа простых текстовых редакторов или графических редакторов. Имя системного диска. Полное имя файла для вывода результатов. Технические требования и условия: Приложение должно выполнять следующие операции: Обеспечивать возможность указывать данные для обмена в одном из процессов. Выполнять чтение и анализ служебной области , расшифровку её содержимого и представление результатов в виде таблицы на устройстве стандартного вывода или в файле. 2. Описания разработанных программ 2.1 Общие сведенияДля выполнения программы необходима ОS Windows 9x/2000/XP, а также более поздние модели такие как Windovs Vista или Windows7/ Программы написаны на языке программирования Object Pascal в среде разработки Delphi 7. 2.2 Функциональное назначениеПрограмма предназначена для обмена данными между пользователями, работающими на одной вычислительной системе под ос Windows на разных терминалах. Также программа осуществляет анализ служебной области системного диска (Partition Table носителя и блока параметров Bios логического диска того же носителя ) 2.3 Описание логической структуры 2.3.1 Логическая структура программы Этап1 Работа программы начинается с запуска приложения OffClient.exe. Перед переходом на главную форму программы появляется окно регистрации (рисунок 1.). Рисунок 1. Окно регистрации в программе. На этом этапе возможно наступление следующих событий : 1) «Событие1» – Кнопка «Войти»; 2) «Событие2» – Кнопка «Закрыть»; Алгоритмы обработчиков событий этой формы. Глобальные переменные: Form2: TForm2 – переменная класса формы, отвечающая за её состояние formClose:boolean – булевская переменная отвечающая за проверку разрешения закрытия формы. Также есть возможность обращаться к объекту TForm1 через подключение к модулю этой формы модуля главной формы (в рабочем каталоге приложения главный модуль имеет имя «Unit1»). 1) Описание события «Событие1»: Выполнение обработчика начинается при нажатии кнопки «Войти». Для успешного выполнения обработчика события «Событие1» необходимо ввести псевдоним в соответствующее поле. После нажатия на кнопку «войти» происходит проверка поля ввода псевдонима, если поле пустое , то выводится сообщение о том, что необходимо ввести псевдоним, если поле псевдонима не пустое, то специальной переменной булевского типа, которая сигнализирует о том, что форма регистрации может быть закрыта присваивается значение TRUE. После этого, происходить передача псевдонима в основную форму программы. Очистка поля Memo1 на главной форме программы. Далее происходит вызов процедуры из главного модуля программы WriteDatainMMF для оповещения других пользователей о том что подключился новый пользователь. Далее происходит закрытие данной формы и переход к основной форме программы. Алгоритм обработки данного события представлен на схеме – (блок схема1) Блок схема 1 Алгоритм обработки события «Событие 1» Данный алгоритм реализует процедуру регистрации пользователя в системе под определённым именем «NICKNAME», которое он вводит в поле псевдонима. При этом программа оповещает других пользователей, которые уже зарегистрированы, о подключении ещё одного пользователя с именем «NICKNAME». После регистрации каждое отправленное сообщение будет маркировано как сообщение от определённого пользователя с именем «NICKNAME». 2) Описание события «Событие2»: Выполнение обработчика события начинается при нажатии кнопки «Закрыть». Алгоритм выполнения обработчика представлен на схеме «блок схема 2». Этап 2На этом этапе происходит переход к главной форме приложения(рисунок2). и происходит обмен сообщениями помощью файла , проецируемого в память. Также на этой форме имеются кнопки для перехода к окну информации о системных носителях. Это сделано исходя из задания на курсовой проект Рисунок2. Форма основного приложения.(программно Form2). На этом этапе возможны следующие события: 1) «Событие1» при на жатии на кнопку «ОТПРАВИТЬ» 2) «Событие2»при нажатии кнопку «Отсоединиться» 3) «Событие3» при нажатии на кнопку «Соединиться» 4) «Событие4» при нажатии на кнопку с изображение каталога. 5) «Событие5» при нажатии на кнопку с изображением дискеты 6) «Событие6» при нажатии на кнопку с изображением восклицательного занка. 7) «Событие7» при нажатии на кнопку «Закрыть» 8) «Событие8» при нажатии на кнопку с изображением жёсткого диска. Алгоритмы обработчиков событий для основной формы программы: Глобальные переменные: TxtFile:TextFile; Файл для сохранения и загрузки истории переписки St:PansiChar; .// строка для хранения текста сообщений об ошибках и программных сообщениях. lincInt:Boolean; переменная для проврки правильности соединения TxtContaningStr:String;// строка , содержащая текст. Используется для хранения текста загружаемой и сохраняемой ситории сообщений. userName:string; Переменная хранящая имя пользователя, работающего с программой. Также в программе используются публичные переменные , доступные во всей сборке(всех модулях данного приложения): HMutex:THandle; - дескриптор объекта типа ThreadRec:TThreadReceiver;-дескриптор объекта типа поток, для принятия сообщений посланных из первичного потока приложения. HEvent:THandle;- дескриптор объекта типа событие. Необходим для сообщения вторичным потокам об отправке данных из первичного потока HFileSender:Thandle;-Дескриптор файла , проецируемого в память, необходим для обращения к файлу ,проецируемому в память, и обмена через него информацией с другими приложениями. 1) Описание события «Событие1»: Наступление события происходит при нажатии на кнопку «ОТПРАВИТЬ». После нажатия на кнопку «ОТПРАВИТЬ» происходит проверка присутствия данных в поле ввода сообщения , если данные отсутствуют, то происходит выход из процедуры, если данные присутствуют, то происходит вызов процедуры WriteDataInMMF. В данной процедуре происходит ожидания объекта типа Mutex в течении бесконечного интервала времени. Это необходимо для реализации обмена сообщениями между несколькими копиями приложения. В данный момент происходит попытка захвата разделяемого ресурса - файа, проецируемого в память. После захвата объекта типа MUTEX происходит проецирование файла на адресное пространство основного процесса. Если файл спроецирован успешно, то происходит запись данных в этот файл, которые становятся доступны для чтения другим процессам, а затем проекция удаляется. Если проекцию создать не удалось, то выводится сообщение: «Не удалось создать проекцию файла». Алгоритм представлен на схемеах(блок схема 2.1, блок схема 2.2). Блок схема 2.1 Алгоритм обработки события «Событие1». Блок схема 2.2 Алгоритм процедуры передачи данных. Данный алгоритм реализуется при нажатии на кнопку «ОТПРАВИТЬ» . В теле обработчика события «Событие1» вызывается данная процедура.(передачи данных. Программно «WriteDataInMMF») 2) Описание события «Событие2»: Данное событие происходит при нажатии на кнопку «Отсоединиться». После нажатия на кнопку «Отсоединится» происходит вызов метода Terminate для потока, который осуществляет приём данный, то есть считывание их из проецируемого файла. Далее , пока поток не остановлен, В проецируемый файл, с помощью рассмотренной выше функции WriteDataInMMF Записываются данные о том, что пользователь отключился. Далее происходит ожидание завершения потока и освобождение ресурсов памяти выделенных этому потоку. После этого происходит уничтожение дескрипторов всех объектов необходимых для обмена информацией таких как: файл проецируемый в память , обьект типа mutex и объект типа, событие, который необходим, для оповещения вторичных потоков приложений о том, что данные записаны в проецируемый файл. Алгоритм работы представлен на схеме (блок схема 2.3). Блок схема 2.3 Алгоритм обработчика события «Событие2». 3) Описание события «Событие3». Событие происходит при нажатии на кнопку «Соединится». При нажатии на данную кнопку происходит создание дескрипторов объектов , необходимых для обмена, эти дескрипторы были рассмотрены выше. Далее происходит запуск на выполнение вторичного потока приложения, который осуществляет считывание данных из проецируемого файла после их записи. Далее происходит запись данных в проецируемый файл с помощью функции. Алгоритм работы представлен на схеме(блок схема 2.4). Блок схема алгоритма события «Событие3». 4) Описание события «Событие4». Загрузка истории сообщений пользователей Событие наступает при нажатии на кнопку: . После нажатия на данную кнопку происходит запуск объекта Open Dialog, в котором выбирается файл для загрузки, далее происходит создание файловой переменной и ассоциирование её с выбранным в Open Dialog файлом, далее в цикле происходит считывание строк из файла и последовательная запись их в поле истории переписки. После считывания файла целиком цикла завершается и происходит закрытие файла. Алгоритм обработки данного события представлен на схеме (блок схема 2.5). Блок схема 2.5 Обработчик события «Событие4». 5) Описание события «Событие 5». Сохранение истории переписки участников чата. Событие наступает при нажатии на кнопку: . При нажатии на эту кнопку появляется диалоговое окно , где предлагается задать имя файлу и каталог, в котором этот файл будет сохранён, далее происходит ассоциирование созданного файла с файловой переменной и открытие этого файла для записи. Построчно текст из поля истории переписки заносится в строковую переменную , а затем в файл. Алгоритм обработчика события данной процедуры представлен на схеме(блок схема 2.6). Блок схема 2.6. Алгоритм обработчика события «Событие 5». 6) Описание события «Событие 6». Это событие происходит по нажатию кнопки. При этом происходит вызов предметного указателя файла справки, который находится в рабочем каталоге приложения. 7) Описание события «Событие7». Происходит по нажатию на кнопку «Закрыть».Алгоритм обработчика представлен на схеме (блок схема 2.7). Блок схема 2.7 обработчик события «Событие7». 8) Описание события «Событие8». Это событие происходит по нажатию на кнопку: . При этом происходит создание третьей формы приложения, переход на которую является третьим этапом построения приложения. Алгоритм обработчика события представлен на схеме (блок схема 2.8). Блок схема 2.7. Этап3 На этом этапе происходит переход к третьему окну приложения. На данном этапе реализуется вторая часть задания на курсовой проект – анализ служебной области системного диска: Форма3 приложения OffClient имеет заголовок «Служебная информация о системных носителях» её вид представлен на рисунке 3. Рисунок 3. Окно отображения служебной информации о носителе. При работе с данной формой возникает 4 события: С1-начать работу с диском С2-Считать BPB (Блок параметров BioS) C3-Счтать Partition Table.(Таблицу разделов диска). С4-Закрытие формы. Данное событие имеет стандартный обработчик. Его описание опущено. Алгоритм обработки событий для третьей формы приложения. Глобальные переменные: hDrive,hMBRDrive: THandle; - Дескрипторы дисков для работы с главной загрузочной записью носитель и блоком параметров Bios. DiscGeometry:TDiscGeometry; - Структрура DiscGeometry Имеет в своём составе такие поля как количество секторов на дорожке , количество дорожек на носителе , количество байт в секторе, 1) Описание события С1. Данное событие происходит при нажатии на кнопку «Начать работу с диском». Если дескрипторы дисков уже существуют, то происходит их уничтожение. Далее происходит создание новых дескрипторов дисков. Если дескрипторы создаются успешно, то происходит заполнение структуры Disk Geometry, в полях которой содержатся данные о диске и вывод их в соответствующее поле. Если дескрипторы создать не удалось, то выводится сообщение об ошибке. Алгоритм обработки данного события представлен на схеме1. Схема 1 - Алгоритм работы обработчика события С1. 2) Описание события С2: Данное событие происходит по нажатию на кнопку «Считать BPB», после этого происходит обработка этого события. Данные из дескриптора диска читаются в буфер, эти данные располагаются в первом секторе логического диска. Если данные считаны, то происходит заполнение специальных таблиц данными из этого буфера, если нет, то выводится специальное сообщение о том, что данные прочитать не удалось. Алгоритм обработчика этого события представлен на схеме2. Схема2 –Обработчик события С2. «Считывание блока параметров BIoS» 3) Описание события С3. Данное событие аналогично предыдущему, за исключением сектора который необходимо прочитать. Данное событие реализуется при нажатии на кнопку «считать Partition Table». Конструктивно данный алгоритм идентичен предыдущему – данные из первого сектора носителя данных читаются в буфер, если они успешно прочитаны происходит заполнение соответствующих страниц данными, если нет, то выводится сообщение о том, что данные не удалось считать в буфер. Алгоритм обработчика события представлен на схеме3. Дополнительные структуры и алгоритмы В данном разделе будут рассмотрены дополнительные логические структуры приложения: 1) Алгоритм работы потока «приёмника» (программно ThreadReceiver) 2) Алгоритм работы модуля, определяющего все активные носители, присутствующие в системе.(программно расположена в модуле HDDInfo). 1) Алгоритм работы потока «приёмника» представлен на схеме 4. Описание алгоритма: В потоке организуется бесконечный цикл(пока поток не остановлен) в этом цикле проверяется некоторое событие, сигнализирующее потоку о том, что данные записаны в файл. После того как событие перешло в сигнальное состояние происходит его обратный сброс в несигнальное состояние. Затем происходит проецирование файла, переменная которого уже создана при запуске основной программы, на адресное пространство процесса. Если проекция создана, то данные читаются из файла и передаются в основную форму программы, а точнее в поле истории переписки. Если создать проекцию не удалось то появляется соответствующее сообщение. Схема 4 – Алгоритм работы потока «приёмника». 2) Описание алгоритма работы модуля, определяющего все активные носители в системе. Алгоритм работы представлен на схемах 5,6,7 и 8. 1. Описание алгоритма (схема5): При выполнении функции, реализующей данный алгоритм, в её теле происходит создание массива имён диско – массив латинских букв A-Z. После этого в цикле происходит считывание имён дисков присутствующих в системе и сравнивание этих имён с именами из массива. Если носитель с данным именем присутствует, то это имя возвращается в качестве результата работы функции. Схема 5 –Алгоритм получения имени носителя, присутствующего в системе. 2. Описание алгоритма (схема6 ): Данный алгоритм необходим для верного определения номера системного носителя. Входными параметрами для этой функции является номер логического диска полученный с помощью API функции GetVolumeInformation. Данный номер считывается в строку и длина этой строки присваивается специальной переменной. Если значение этой переменной не равно восьми, происходит выход из процедуры, если и значение номера не меняется, если длина равна 8, то в цикле происходит изменение номера, считанного с помощью функции GetVolumeInformation, на правильный. В семействе ОС Windows в поздних версиях таких как «XP», «Vista» и «7» номер, полученный с помощью функции GetVolumeInformation является общим для всех носителей присутствующих в системе, хотя на практике это не является таковым. Схема 6 –алгоритм работы функции, определяющей верный номер логического диска. Данная функция необходима для правильного определения номера логического диска, если программа запущена под операционной системой Windows Xp , или более поздних. Схема 7-Алгоритм процедуры для получения системной информации о логическом носителе. Входным параметром для данной функции является имя логического диска, которое извлекается при вызове функции : GetDisk, алгоритм которой представлен на схеме 5. 3. Описание алгоритма (схема 8). Этот алгоритм реализуется при вызове функции, определяющей все присутствующие в системе диски, при запуске третьей формы программы(этап3). В данном алгоритме реализуется, сперва, вызов функции GetDisks, для получения имён всех дисков присутствующих в системе и записи этих имён в строку, далее в цикле происходит считывание символа из строки и получение с помощью функции GetVolumeInformation всех данных о диске с именем совпадающем со считанным символом. Если данные считаны , то происходи вывод их в специальную компоненту, если нет , то происходит заполнение полей отображающих данные о носителе нулевыми значениями. Схема 8 – Алгоритм работы функции вызова процедуры получающей данные о всех активных носителях системы. 2.3.2 Логическая структура справочной системы. Сначала в файле «текст справки.rtf» в редакторе MS Word составляется содержание разделов справки. Затем с помощью программы Microsoft Help Workshop создается оглавление справочной системы и проект. В оглавлении вводятся названия всех разделов и номера. В проекте указывается файл rtf, файл содержания, идентификаторам разделов сопоставляются номера и названия, устанавливаются настройки и производится компиляция. После компиляции создается файл справочной системы CПРАВКА.HLP. Рисунок 3.1 - Пример раздела в файле «текст справки.rtf». Рисунок 3.2 - Пример файла содержания справочной системы . Рисунок 3.3 - Пример файла проекта справочной системы Рисунок 4.4 Пример окна справки. 2.3.3 Создание программы инсталлятора Для создания инсталлятора использовалась программа InstallShield Express. Рисунок 3.3.1 – Общая информация. Рисунок 3.3.2 - Тип установки. Рисунок 3.3.4 - Содержание устанавливаемых файлов проекта Рисунок 3.3.5 - Создание ярлыков Рисунок 3.3.6 - Выбор диалоговых окон. Рисунок 3.3.7 - Программа установки. Рисунок 3.3.8 - Ход установки. Рисунок 3.3.9 - Окончание установки. 2.4 Используемые технические средстваПри выполнении данной курсовой работы используется персональный компьютер операционной системой Windows7 с процессором IntelCore2Duo6300. Данный компьютер оснащен всеми устройствами необходимыми для работы в среде разработки Delphi 7 и последующем запуске полученных программ. 2.5 Вызов и загрузкаВызов программы осуществляется выполнением приложения OffClient, ярлыки которого находятся на рабочем столе и панели программ Windows. 2.6 Входные данныеВходными данными в данной программе являются сообщения ,которые вы вводите в поле ввода сообщений. Также входными данными являются имена логических дисков, которые выбираются из выпадающего списка. 2.7 Выходные данныеВыходными данными в данном приложении являются: Для первого задания это сообщения пришедшие от пользователей других копий программы, а также сообщения, которые были посланы из текущей версии приложения Для второго задания выходными данными являются данные о системном носителе, который выбирается из списка доступных носителей. Эта информация отображается в полях и таблицах второй части программы. 3. Программа и методика испытаний3.1 Объект испытанийОбъектом испытаний является приложение Redactor.exe. 3.2 Цель испытанийЦелью испытании приложения является выяснение возможных ошибок во время выполнения программы, которые не были обнаружены на стадии разработки. 3.3 Требования к программеТребуется проверить работу логической и интерфейсной частей программ. А так же обеспечить контроль входных и выходных данных. 3.4 Требования к программной документацииВ приложении необходимо запустить справочную систему. 3.5 Средства и порядок испытанийИспытание приложения будет производиться 2-мя методами: “белым и черным ящиками”. 3.6 Методы испытаний 3.6.1 Тестирование методом белого ящика:Прежде чем нумеровать текст программы, необходимо все циклы изменить на структурированные, сложные условия разбить на простые, а линейные части программы(по возможности) записать в одну строку. Затем строки текста функции нумеруются: номер получают только те строки, которые содержат операторы, условия или закрывающие операторные скобки. 1) Тестирование процедуры выполняющей запись данных в проецируемый файл(2 этап выполнения программы). В данном случае это является первым заданием курсового проекта - обмен данными между приложениями с помощью файла проецируемого в память. 1инициализация 2if Edit1.Text <> '' then Begin WriteDataInMMF(Nicname+' Написал:'+#13#10+string(Edit1.Text)); (тело функции WriteDataInMMF(вхдными данными является строка S) имеет следующий вид): begin 3 WaitForSingleObject(HMutex, INFINITE); PBaseAdress:=MapViewOfFile(HFileSender,FILE_MAP_WRITE,0,0,Length(s)+4); 4 if(PBaseAdress = nil) then begin 5 CloseHandle(HFileSender); st:='не удалось передать данные'; Application.MessageBox(st,'Сообщение...',MB_OK); exit; end; begin 6 integer(PBaseAdress^):=length(s); CopyMemory(Pointer(Integer(PBaseAdress)+4),PChar(s),length(s)); UnmapViewOfFile(PBaseAdress); SetEvent(HEvent); ReleaseMutex(HMutex); 7 end; 8 end; 9 Edit1.Text:=''; 10 end else 11 exit; 12 end; Рисунок 4.1 – Потоковый граф обработчика события «Событие1» которое происходит при нажатии на кнопку «ОТПРАВИТЬ» на основной форме программы. Цикломатическая сложность потокового графа: 1) V(G) = 3 региона; 2) V(G) = 13 дуг - 12 узлов + 2 = 3; 3) V(G) = 2 предикатных узла +1 = 3. Базовое множество независимых линейных путей: Путь 1:1-2-11-12 . Путь 2: 1-2-3-4-5-12. Путь 3: 1-2-3-4-5-6-7-8-9-10-12. Таблица тестовых вариантов 4.1
2) Тестирование процедуры выполняющей создание дескрипторов логического диска с которым ведётся работа и дескриптора жёсткого диска которому принадлежит этот логический диск(3 этап выполнения программы ). 1 инициализация 2 if hDrive <> 0 then 3CloseHandle(hDrive); 4 if hMBRDrive <> 0 then 5CloseHandle(hMBRDrive); 6 discNameBPB:='\\.\'+DriveComboBox1.Drive+':'; discNameMBR:='\\.\PHYSICALDRIVE'+intToStr(0); hMBRDrive:= CreateFile(PChar(discNameMBR),GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0); hDrive:= CreateFile(PChar(discNameBPB),GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0); 7 if (hDrive <> INVALID_HANDLE_VALUE) and (hMBRDrive <> INVALID_HANDLE_VALUE) then begin 8 Result := DeviceIoControl(hDrive,IOCTL_DISK_GET_DRIVE_GEOMETRY,nil,0, @DiscGeometry,SizeOf(TDiscGeometry),junk,nil) and (junk = SizeOf(TDiscGeometry)); DiscGeometryShow(); 9 end else begin 10 ShowMessage('не удалось создать дескрипторы дисков'); 11 exit; end; 12 end; Рисунок 4.2 Потоковый граф обработчика события «С1» которое происходит при нажатии на кнопку «Начать работу с диском» Цикломатическая сложность потокового графа: 1) V(G) = 4 регионов; 2) V(G) = 14 дуга - 12 узлов + 2 = 4; 3) V(G) = 3 предикатных узлов +1 = 4. Путь 1:1-2-4-6-7-10-11-12; Путь 2:1-2-3-4-6-7-10-11-12. Путь 3: 1-2-4-5-6-7-10-11-12. Путь 4:1-2-3-4-5-7-8-9-12.
3) Тестирование процедуры считывающей блок параметров Bios - событие «С2» (происходит при нажатии на кнопку «Считать BPB»)логического диска дескриптор которого был создан в процедуре обрабатывающей событие «С1» при нажатии на кнопку «Начать работу с диском» 1инициализация 2IfReadSectors(hDrive,0,1,@buffer,DiscGeometry.BytesPerSector) = DiscGeometry.BytesPerSector then begin 3for i:= 1 to 16 do 4Grid1.Cells[i,0]:=intToHex((i-1),1); 5i:=1; j:=1; k:=1; 6while k<=DiscGeometry.BytesPerSector do begin 7 if i=1 then 8 Grid1.Cells[0,j]:=IntToHex(((j-1)*16+(i-1)),3); 9 Grid1.Cells[i,j]:=IntToHex(Buffer[k],2); inc(k); inc(i); 10 if i>16 then begin 11 i:=1; j:=j+1; Grid1.RowCount:= Grid1.RowCount+1; 12end; 13end; 14{линейный блок расшифровки данных BPB} end else 15ShowMessage(‘не удалось считать BPB’); 16end 17end; программа многопоточный приложение служебный Рисунок 4.3 – Потоковый граф обработчика события С2 (Считывание блока параметров Bios). Цикломатическая сложность потокового графа: 1) V(G) = 6 регионов; 2) V(G) = 21дуг - 17 узлов + 2 = 6; 3) V(G) = 5 предикатных узлов +1 = 6. Путь 1:1-2-15-16-17; Путь 2:1-2-3-4-5-6-7-9-10-12-13-14-17. Путь 3: 1-2-3-4-5-6-7-8-9-10-12-13-14-16-17. Путь 4:1-2-3-4-5-6-7-9-10-11-12-13-14-16-17. Путь 5:1-2-3-4-5-6-7-8-9-10-11-12-13-14-16-17. Путь 6: 1-2-3-4-3-4-5-6-7-9-10-12-13-6-7-8-9-10-11-12-13-14-16-17.
4) Тестирование процедуры, считывающей таблицу разделов носителя(событие «С3» - происходит при нажатии на кнопку «Считать Partition Table»), к которому принадлежит ,выбранный из выпадающего списка логический диск 1инициализация. 2Memo2.Clear; 3If.ReadSectors(hMBRDrive,0,1,@buffer,DiscGeometry.BytesPerSector)= DiscGeometry.BytesPerSector then begin 4for i:= 1 to 16 do 5Grid2.Cells[i,0]:=intToHex((i-1),1); 6i:=1; j:=1; k:=1; 7while k<=DiscGeometry.BytesPerSector do begin 8if i=1 then 9Grid2.Cells[0,j]:=IntToHex(((j-1)*16+(i-1)),3); 10Grid2.Cells[i,j]:=IntToHex(Buffer[k],2); inc(k); inc(i); 11if i>16 then begin 12 i:=1; j:=j+1; Grid2.RowCount:= Grid2.RowCount+1; 13 end; 14end; begin 15{Линейный блок расшифровки значений полученных в буфере после чтения сектора} 16end else 17ShowMessage('Не удалось считать блок PartitionTable'); 18end; Рисунок 4.4 – Потоковый граф обработчика события «С3» (кнопка «Считать PartitionTable ») Цикломатическая сложность потокового графа: 1) V(G) = 6 регионов; 2) V(G) = 22 дуга - 18 узлов + 2 = 6; 3) V(G) = 5 предикатных узлов +1 = 6. Путь 1:1-2-17-18; Путь 2:1-2-3-4-5-6-7-8-10-11-13-14-15-16-18; Путь 3:1-2-3-4-5-6-7-8-9-10-11-13-14-15-16-18; Путь 4: 1-2-3-4-5-6-7-8-10-11-12-13-14-15-16-18; Путь 5: 1-2-3-4-5-4-5-6-7-8-9-10-11-13-14-15-16-18; Путь 6: 1-2-3-4-5-4-5-6-7-8-10-11-12-13-14-7-8-9-10-11-13-14-15-16-18;
Дополнительный тест Тестирование алгоритма работы потока, который также относится к основному заданию курсового проекта. 1инициализация. 2while (not terminated) do begin 3 WaitForSingleObject(Form1.HEvent, INFINITE); 4 ResetEvent(Form1.HEvent); 5 try // резерв. память в потоке для этотой проекции 6PBaseAdress:=MapViewOfFile(Form1.HFileSender, FILE_MAP_READ,0,0,65536); 7 if (PBaseAdress = nil) then begin 8 CloseHandle(Form1.HFileSender); st:='не удалось отобразить файл на адресное пространство'; Application.MessageBox(st,'Сообщение...',MB_OK); form1.BitBtn2.Visible:=false; form1.Button1.Visible:=false; 9 exit; 10end; 11 nlineSize:=integer(PBaseAdress^); SetLength(TextString,nlineSize); CopyMemory(PChar(TextString),Pointer(Integer(PBaseAdress)+4),nlineSize); Form1.Memo1.Text:=Form1.Memo1.Text+'---------'+#13#10; Form1.Memo1.Text:=Form1.Memo1.Text+TextString+#13#10; sendmessage(Form1.memo1.handle, em_linescroll, 0, Form1.memo1.lines.count-1); UnmapViewOfFile(PBaseAdress); finally 12end; 13end; Рисунок 4.5 – Потоковый граф обработчика потока(данный обработчик выполняется постоянно после запуска программы и если не была нажата кнопка «отсоединится при работе программы») Цикломатическая сложность потокового графа: 1) V(G) = 3 регионов; 2) V(G) = 14 дуг - 13 узлов + 2 = 3; 3) V(G) = 2 предикатных узлов +1 = 3. Путь 1:1-2-3-4-5-6-7-8-9-13; Путь 2:1-2-3-4-5-6-7-10-11-12-13; Путь 3:1-2-3-4-5-6-7-8-9-10-11-12-2-3-4-5-6-7-10-11-12-13;
3.6.2 Тестирование методом черного ящика 1) Тестирование процедуры, выполняющей запись данных в проецируемый файл (Рисунок 4.6. ). (Этап выполнения программы 2 «Событие 1»). Предусловие : Текст сообщения должен быть обязательно введён. Постусловие: Если проекция файла создана, и объект типа поток сработал нормально, то вывод текста сообщения в поле истории переписки. Рисунок 4.6 – Дерево разбиений для события «Событие1» (первое задание)
2) Тестирование процедуры выполняющей создание дескрипторов носителя с которым ведётся работа (Рисунок 4.7). (Этап выполнения программы 3 , событие С1). Предусловие: Программа должна быть запущена от имени администратора. Постусловие: 1 Должен быть выбран присутствующий носитель. 2 Если дескрипторы файлов успешно созданы и данные прочитаны в буфер, то- вывод информации в таблицы. Рисунок 4.7 Дерево разбиений для процедуры, выполняющей создание дескрипторов носителя(Этап выполнения программы 3 события C1).
3)Тестирование процедуры, выполняющей считывание блока параметров Bios (Рисунок 4.8). (Этап выполнения программы 3 , событие «С2»). Предусловие: Дескрипторы должны быть созданы. Постусловие: Файловая система должна быть FAT32. Рисунок 4.8 –Дерево разбиений для процедуры, выполняющей считывание блока BPB для выбранного носителя.
4)Тестирование процедуры, считывающей таблицу разделов жёсткого диска(Рисунок 4.9). (Этап выполнения программы 3 , событие «С3»). Предусловие: Программа должна быть запущена от имени администратора. Постусловие: Дескрипторы должны быть созданы. Рисунок 4.9 – Дерево разбиений для процедуры считывающей таблицу разделов носителя.
5)Тестирование процедуры работы потока.(Рисунок 4.10). Предусловие: 1.Поток должен быть запущен. 2.Средства синхронизации созданы. Постусловие: Файл проецируемый в память должен быть успешно создан. Рисунок 4.10 – Дерево разбиений для процедуры работы потока.
4. Эксплуатационные документы
4.1 Руководство программиста 4.1.1 Общие сведения о программе Программа предназначена для обмена сообщениями между копиями этой программы с помощью файла, проецируемого в память. А также для анализа рабочей области системного диска, т.е анализ и расшифровку блока параметров Bios и анализ и расшифровку таблицы разделов носителя. 4.1.2 Структура программы После запуска приложения появляется форма «Авторизация» для присвоения пользователя специального псевдонима для обмена информацией. Форма содержит две кнопки: «Войти» и «Закрыть». По нажатию кнопки «закрыть» происходит выход из приложения. По нажатию кнопки «войти» происходит переход на основную форму программы, данная форма содержит поле вывода сообщений – «поле истории переписки», также поле ввода сообщений, кнопку «ОТПРАВИТЬ» для отправки сообщений, а также кнопки отсоединиться, закрыть и соединится, которая будет появится на форме только после нажатия на кнопку «отсоединиться». Также на форме присутствует панель инструментов с кнопками : 1. Сохранить историю переписки, 2. Загрузить историю переписки. 3. Получить данные о носителях. 4. Справка. При нажатии на первую кнопку появляется диалоговое окно, в котором необходимо выбрать файл, содержащий историю переписки, если такой имеется, и вывод содержимого этого файла в поле истории переписки. При нажатии на вторую кнопку происходит открытие диалогового окна, в котором предлагается назначить сохраняемому файлу имя и каталог, в котором данный файл будет сохранён. Содержимым данного файла будет являться история последней переписки. При нажатию на четвёртую кнопку происходит запуск файла справочной системы, содержащей всю необходимую информацию о программе. При нажатии на третью кнопку происходит открытие дополнительного окна программы. Дополнительное окно программы имеет заголовок «Служебная информация о носителях». Это окно содержит поле вывод информации о всех носителях присутствующих в системе . Поле вывода краткой информации о носителе, поле вывода расшифрованной информации о блоке параметров Bios, поле вывода расшифрованной информации о таблице разделов носителя, а также две таблицы, содержащие 16ричные значения первого сектора логического диска- блок параметров Bios и 16ричные значения первого сектора носителя, к которому относится выбранный логический диск (в этом секторе находится таблица разделов логического диска – Partition Table). Также на форме находятся 4 кнопки: 1. Начать работу с диском 2. Считать BPB(блок параметров Bios) 3. Считать Partition Table. 4. Закрыть. При нажатии на первую кнопку происходит вывод краткой информации о носителе. При нажатии на кнопку «Считать BPB» происходит считывание блока BPB и заполнение значениями таблицы содержащей расшифрованные данные из BPB и таблицы, содержащей 16ричные значения считанные из BPB, выбранного логического диска. При нажатии на кнопку – «Считать Partition Table» происходит считывание первого сектора носителя информации и заполнение данными таблицы, содержащей расшифрованные данные о таблице разделов диска и таблицы содержащей 16ричные значения считанные из первого сектора носителя. 4.1.3 Проверка программы Входные данные : строка сообщения «сообщение №1»; логический диск «H». Выходные данные : «сообщение№1»; Краткая информация о носителе: «Вы просматриваете логический диск: h Количество цилиндров: 247 Тип носителя: съёмный носитель Дорожек на цилиндре: 255 Секторов на дорожке: 63 Байт в секторе: 512» Информация о таблице разделов диска: Первый элемент таблицы разделов системного диска: Признак загрузки: 80 Начало раздела диска{Головка: 1 Сектор: 1 Цилиндр: 0 } Тип раздела {Ос: 7 } Конец раздела диска{Головка: 254 Сектор: 255 Цилиндр: 255 } Номер Сектора {: 63 } Размер раздела {: 61432497 } Второй элемент таблицы разделов системного диска: Признак загрузки: 00 Начало раздела диска{Головка: 255 Сектор: 255 Цилиндр: 15 } Тип раздела {Ос: 254 } Конец раздела диска{Головка: 255 Сектор: 255 Цилиндр: 240 } Номер Сектора {: 61432560 } Размер раздела {: 318782480 } 4.1.4 Дополнительные возможности Программа имеет справочную систему, для её запуска необходимо нажать кнопку , или F1 на клавиатуре. Также программа определяет носители доступные в системе, это происходит автоматически при переходе на третью форму программы. 4.1.5 Сообщения системному программисту 1) При подключении, если не удалось создать проекцию файла при запуске программы, появляется сообщение: Рисунок 5.1 –Содержание сообщения 2)Если не удалось создать объект типа Mutex для обмена сообщениями с другими программами, появляется сообщение: Рисунок 5.2 – Содержание сообщения. 3) Если не удалось наладить приём сообщений от других копий программ, появляется сообщение: Рисунок 5.3 – Текст сообщения. 4) Если не удалось создать объект типа события для оповещения потока о том, что данные записаны в проецируемый файл, появляется сообщение: Рисунок 5.4 –Текст сообщения. 5) Если не удалось передать данные (записать данные в проецируемый файл) , появляется сообщение: Рисунок 5.6 – Текст сообщения. 4.2 Руководство пользователя 4.2.1 Назначение и условия выполнения программы Данная программа предназначена для обмена сообщениями между копиями данной программы, а также для получения системной информации о носителях. Для выполнения программы необходим IBM-совместимый персональный компьютер, оснащенный процессором Intel или аналогичным и операционной системой семейства Windows. 4.2.2 Обращение к программе для запуска: Для запуска программы необходимо запустить приложение с Redactor.exe . Это делается с помощью ярлыка , который появляется на рабочем столе после установки, с именем OffClient. 4.2.3 Входные и выходные данные: Входными и выходными данными при обмене сообщениями являются сами сообщения. При получении служебных данных о носителях входными данными являются имена этих носителей, а выходными – данные о них, такие как: Количество цилиндров, тип носителя, дорожек на цилиндре, секторов на дорожке, байт в секторе и т.д. 4.2.4 Сообщения оператору: 1) Если не введён псевдоним при регистрации то появится сообщение: Рисунок 5.7 - Текст сообщения. 2) Если не удалось передать сообщение: Рисунок 5.8 – Текст сообщения. Приложение1) Текст основного модуля программы program Redactor; uses Forms, Unit1 in 'Unit1.pas' {Form1}, ThrdRcvr in 'ThrdRcvr.pas', Unit2 in 'Unit2.pas' {Form2}, Unit3 in 'Unit3.pas' {Form3}, HDDInfo in 'HDDInfo.pas'; {$R *.res} begin Application.Initialize; Application.HelpFile:='СПРАВКА.HLP'; Application.CreateForm(TForm1, Form1); Application.ShowMainForm:=false; Application.CreateForm(TForm2, Form2); Application.Run; end. 2) Текст модуля Unit1: unit Unit1; //Основной модуль interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ThrdRcvr, StdCtrls, Buttons, Menus,ToolWin, ComCtrls, ActnMan, ActnColorMaps, ImgList, ExtCtrls,Unit3; const MMFName:PChar = 'MMFProectFile'; MutxName:PChar = 'UniqMutexName'; EvntName:Pchar = 'ChatEventName'; SHARED_MEMORY_SIZE = 65536; type TForm1 = class(TForm) Memo1: TMemo; OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; MainMenu1: TMainMenu; N1: TMenuItem; N3: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; N7: TMenuItem; BitBtn2: TBitBtn; BitBtn3: TBitBtn; Edit1: TEdit; Button1: TButton; Button2: TButton; ToolBar1: TToolBar; OpenToolButton: TToolButton; SaveAsToolButton: TToolButton; ToolButton3: TToolButton; ImageList1: TImageList; StatusBar1: TStatusBar; Timer1: TTimer; ToolButton1: TToolButton; N2: TMenuItem; N8: TMenuItem; procedure Button1Click(Sender: TObject); procedure N4Click(Sender: TObject); procedure BitBtn2Click(Sender: TObject); procedure BitBtn3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure CloseHandles; procedure CreateHandles; procedure Button2Click(Sender: TObject); procedure WriteDataInMMF(s:string); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure N5Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure ToolButton3Click(Sender: TObject); procedure ToolButton1Click(Sender: TObject); procedure N8Click(Sender: TObject); procedure N2Click(Sender: TObject); private procedure AppHint(Sender: TObject); public HMutex:THandle; ThreadRec:TThreadReceiver; HEvent:THandle; HFileSender:Thandle; NicName:string; end; var Form1: TForm1; TxtFile:TextFile;// пременная файла St:PansiChar; lincInt:Boolean; TxtContaningStr:String; userName:string; implementation {$R *.dfm} //процедура для показа кртких справок procedure TForm1.AppHint(Sender: TObject); begin StatusBar1.SimpleText:=Application.Hint; //для отображения ииформации в панели соостояния end; //закрытие всех хендлов в этой копии программы procedure TForm1.CloseHandles(); begin CloseHandle(HFileSender); CloseHandle(HMutex); CloseHandle(HEvent); end; // создание всех необходимых объектов procedure TForm1.CreateHandles; begin // проекция файла HFileSender:=CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SHARED_MEMORY_SIZE,MMFName); lincInt:=(GetLastError() <> ERROR_ALREADY_EXISTS); if HFileSender = 0 then begin st:='не удалось создать проекцию файла'; Application.MessageBox(st,'Сообщение...',MB_OK); exit; end; // мьютекс HMutex:=CreateMutex(nil,false,MutxName); if HMutex = 0 then begin CloseHandle(HFileSender); st:='не удалось синхронизировать приложение'; Application.MessageBox(st,'Сообщение...',MB_OK); exit; end; // событие HEvent:=CreateEvent(nil,true,false,EvntName); if HEvent = 0 then begin CloseHandle(HFileSender); CloseHandle(HMutex); st:='не удалось осуществить обмен сообщениями'; Application.MessageBox(st,'Сообщение...',MB_OK); exit; end; end; // отсоединиться procedure TForm1.Button1Click(Sender: TObject); begin ThreadRec.Terminate; WriteDataInMMF('Пользователь '+NicName+' отключился'); ThreadRec.WaitFor; ThreadRec.Free;// правильно уничтожаем поток CloseHandles(); button2.Visible:=true; button1.Visible:=false; bitbtn2.Visible:=false; end; // загрузить историю переписки procedure TForm1.N4Click(Sender: TObject); begin if OpenDialog1.Execute then begin AssignFile(TxtFile,OpenDialog1.FileName); Reset(TxtFile); Memo1.Text:=Memo1.Text +'{-----------Загруженная переписка ниже-------------}' + #13#10; while not eof(TxtFile) do begin readln(TxtFile,TxtContaningStr); Memo1.Text:=Memo1.Text + TxtContaningStr + #13#10; end; Memo1.Text:=Memo1.Text +'{-----------Загруженная переписка выше -------------}' + #13#10; CloseFile(TxtFile); end; end; //процедура записи данных в MMF procedure TForm1.WriteDataInMMF(s:string); var PBaseAdress:Pointer; begin WaitForSingleObject(HMutex, INFINITE); PBaseAdress:=MapViewOfFile(HFileSender,FILE_MAP_WRITE,0,0,Length(s)+4); if(PBaseAdress = nil) then begin CloseHandle(HFileSender); st:='не удалось передать данные'; Application.MessageBox(st,'Сообщение...',MB_OK); exit; end; begin integer(PBaseAdress^):=length(s); CopyMemory(Pointer(Integer(PBaseAdress)+4),PChar(s),length(s)); UnmapViewOfFile(PBaseAdress); SetEvent(HEvent); ReleaseMutex(HMutex); end; end; // процедура записи данных в PBaseAdress procedure TForm1.BitBtn2Click(Sender: TObject); begin if Edit1.Text <> '' then begin WriteDataInMMF(Nicname+' написал:'+#13#10+string(Edit1.Text)); Edit1.Text:=''; end else exit; end; // Закрытия формы procedure TForm1.BitBtn3Click(Sender: TObject); begin close; end; //создаём хендлы и потоки procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Clear; // создание потока принимающего данные из файла ThreadRec:=TThreadReceiver.Create(false); ThreadRec.Priority:=tpLowest; CreateHandles();// создаем хендлы end; // соединение procedure TForm1.Button2Click(Sender: TObject); begin CreateHandles(); ThreadRec:=TThreadReceiver.Create(false); button2.Visible:=false; button1.Visible:=true; bitbtn2.Visible:=true; WriteDataInMMF(NicName+' Cоединился!'); end; // Запрос подтверждения при закрытии формы procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin case messageBox(Handle,'Действительно выйти?','Внимание!', MB_YESNO) of IDYES: begin if Button1.Visible = true then begin ThreadRec.Terminate; WriteDataInMMF('Пользователь '+NicName+' отключился'); ThreadRec.WaitFor; ThreadRec.Free; CanClose:=true; end else CanClose:=true; end; IDNO: CanClose:=false; end; end; //Сохранить историю переписки procedure TForm1.N5Click(Sender: TObject); begin If SaveDialog1.Execute then begin AssignFile(TxtFile,SaveDialog1.FileName); rewrite(TxtFile); TxtContaningStr:= Memo1.Text; Write(TxtFile,TxtContaningStr); CloseFile(TxtFile); St:='Файл сохранён'; Application.MessageBox(St,'Сообщение...',MB_OK); exit; end else begin St:='файл не сохранён'; Application.MessageBox(St,'Сообщение...',MB_OK); end; end; procedure TForm1.Timer1Timer(Sender: TObject); begin if Form1.Visible = true then begin Application.OnHint:=AppHint; Timer1.Enabled:=false; Timer1.Destroy; end; end; procedure TForm1.ToolButton3Click(Sender: TObject); begin Application.CreateForm(TForm3, Form3); Application.ShowMainForm:=false; Form3.Visible:=true; end; procedure TForm1.ToolButton1Click(Sender: TObject); begin //вызов справки (основная форма программы) Application.HelpContext(2); end; procedure TForm1.N8Click(Sender: TObject); begin Application.HelpCommand(HELP_FINDER,0); end; procedure TForm1.N2Click(Sender: TObject); begin ShowMessage('Программу подготовил студент группы 742:'+#13#10+'Шипилов Д.А.'); end; end. 3) Текст модуля Unit2 (Модуль формы «Авторизация»): unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,Unit1, ComCtrls, Buttons; type TForm2 = class(TForm) Button2: TButton; Edit1: TEdit; Label1: TLabel; BitBtn1: TBitBtn; procedure Button2Click(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure BitBtn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; formClose:boolean=false; implementation {$R *.dfm} // закрытие формы procedure TForm2.Button2Click(Sender: TObject); begin close; end; // запрос подтверждения при завершении программы из дочерней формы procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin if formClose = true then begin CanClose:=true; end else begin case messageBox(Handle,'Действительно выйти?','Внимание!', MB_YESNO) of IDYES: begin Application.Terminate; end; IDNO: CanClose:=false; end; end; end; procedure TForm2.BitBtn1Click(Sender: TObject); var St:PansiChar; begin if Edit1.Text <> '' then begin formClose:=true; Form1.Memo1.Clear; Form1.NicName:=Edit1.Text; Form1.WriteDataInMMF('Пользователь '+Form1.NicName+' подключился'); Application.ShowMainForm:=true; Form1.Visible:=true; Form2.Close; end else begin st:='Пожалуйста введите псевдоним для авторизации'; Application.MessageBox(st,'Сообщение...',MB_OK); exit; end; end; end. 4) Модуль Unit 3 (Модуль формы, осуществляющей работу с носителями информации в системе): unit Unit3; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, FileCtrl, ExtCtrls, Grids, ValEdit,HDDInfo, Buttons, ComCtrls; const IOCTL_DISK_GET_DRIVE_GEOMETRY = $70000; type // версия ОС TWinVersion = (wvUnknown,wv95,wv98,wvME,wvNT3,wvNT4,wvW2K,wvXP,wv2003,wvVista,wv7); //геометрия TDiscGeometry = packed record Cylinders: Int64; // колличество цилиндров MediaType: DWORD; // тип носителя TracksPerCylinder: DWORD; // дорожек на цилиндре SectorsPerTrack: DWORD; // секторов на дорожке BytesPerSector: DWORD; // байт в секторе end; //TForm TForm3 = class(TForm) Button1: TButton; DriveComboBox1: TDriveComboBox; Panel1: TPanel; Button2: TButton; Grid1: TStringGrid; Button3: TButton; GroupBox1: TGroupBox; bpbList: TValueListEditor; Label1: TLabel; GroupBox2: TGroupBox; Disks: TLabel; BitBtn1: TBitBtn; GroupBox3: TGroupBox; Memo1: TMemo; Grid2: TStringGrid; Label2: TLabel; Memo2: TMemo; Label3: TLabel; procedure Button1Click(Sender: TObject); procedure DiscGeometryShow; procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure FormActivate(Sender: TObject); // Result = LoDWORD private { Private declarations } public { Public declarations } end; var Form3: TForm3; hDrive,hMBRDrive: THandle; DiscGeometry:TDiscGeometry; typeOfDisc:string; implementation {$R *.dfm} // определение версии ОС function DetectWinVersion : TWinVersion; var OSVersionInfo : TOSVersionInfo; begin Result := wvUnknown; // Неизвестная версия ОС OSVersionInfo.dwOSVersionInfoSize := sizeof(TOSVersionInfo); if GetVersionEx(OSVersionInfo) then begin case OSVersionInfo.DwMajorVersion of 3: Result := wvNT3; // Windows NT 3 4: case OSVersionInfo.DwMinorVersion of 0: if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then Result := wvNT4 // Windows NT 4 else Result := wv95; // Windows 95 10: Result := wv98; // Windows 98 90: Result := wvME; // Windows ME end; 5: case OSVersionInfo.DwMinorVersion of 0: Result := wvW2K; // Windows 2000 1: Result := wvXP; // Windows XP 2: Result := wv2003; // Windows 2003 end; 6: case OSVersionInfo.DwMinorVersion of 0: Result := wvVista; // Windows Vista 1: Result := wv7; // Windows 7 end; end; end; end; // для вывода версии function DetectWinVersionStr : string; const VersStr : array[TWinVersion] of string = ( 'Unknown', 'Windows 95', 'Windows 98', 'Windows ME', 'Windows NT 3', 'Windows NT 4', 'Windows 2000', 'Windows XP', 'Windows 2003', 'Windows Vista', 'Windows Seven'); begin Result := VersStr[DetectWinVersion]; end; // для перемещения по диску function __Mul(a,b: DWORD; var HiDWORD: DWORD):DWORD; asm mul edx mov [ecx],edx end; // Чтение сектора жесткго диска(Вызыв когда работа с диском начата) function ReadSectors(hDrive:Thandle; StartingSector, SectorCount: DWORD; Buffer: Pointer; BytesPerSector: DWORD): DWORD; var br,TmpLo,TmpHi: DWORD; begin Result := 0; TmpLo := __Mul(StartingSector,BytesPerSector,TmpHi); if SetFilePointer(hDrive,TmpLo,@TmpHi,FILE_BEGIN) = TmpLo then begin SectorCount := SectorCount*BytesPerSector; if ReadFile(hDrive,Buffer^,SectorCount,br,nil) then Result := br; end; end; // вывод геометрии procedure TForm3.DiscGeometryShow; begin Memo1.Clear; Memo1.Text:='Вы просматриваете логический диск: '+DriveComboBox1.Drive+#13#10; Memo1.Text:= memo1.Text + 'Количество цилиндров: '+inttoStr(DiscGeometry.Cylinders)+#13#10; case DiscGeometry.MediaType of 12:typeOfDisc:=' жёсткий диск'; 11:typeOfDisc:=' съёмный носитель'; end; Memo1.Text:= memo1.Text + 'Тип носителя: '+typeOfDisc+#13#10; Memo1.Text:= memo1.Text + 'Дорожек на цилиндре: '+intToStr(DiscGeometry.TracksPerCylinder)+#13#10; Memo1.Text:= memo1.Text + 'Секторов на дорожке: '+intToStr(DiscGeometry.SectorsPerTrack)+#13#10; Memo1.Text:= memo1.Text + 'Байт в секторе: '+intToStr(DiscGeometry.BytesPerSector)+#13#10; end; //создаем файл диска/выводим геомертию //начинаем работу с жёстким диском procedure TForm3.Button1Click(Sender: TObject); var discNameBPB,discNameMBR:string; junk:Cardinal; result:boolean; begin if hDrive <> 0 then CloseHandle(hDrive); if hMBRDrive <> 0 then CloseHandle(hMBRDrive); discNameBPB:='\\.\'+DriveComboBox1.Drive+':'; discNameMBR:='\\.\PHYSICALDRIVE'+intToStr(0); hMBRDrive:= CreateFile(PChar(discNameMBR),GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0); hDrive:= CreateFile(PChar(discNameBPB),GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0); if (hDrive <> INVALID_HANDLE_VALUE) and (hMBRDrive <> INVALID_HANDLE_VALUE) then begin Result := DeviceIoControl(hDrive,IOCTL_DISK_GET_DRIVE_GEOMETRY,nil,0, @DiscGeometry,SizeOf(TDiscGeometry),junk,nil) and (junk = SizeOf(TDiscGeometry)); DiscGeometryShow(); end else begin ShowMessage('Не возможно создать дескрипторы носителя'); exit; end; end; // Чтение и рашифровка BPB procedure TForm3.Button2Click(Sender: TObject); var i,j,k:integer; read:Cardinal; s:string; buffer: array[1..131072] of byte; begin if ReadSectors(hDrive,0,1,@buffer,DiscGeometry.BytesPerSector) = DiscGeometry.BytesPerSector then begin for i:= 1 to 16 do Grid1.Cells[i,0]:=intToHex((i-1),1); i:=1; j:=1; k:=1; while k<=DiscGeometry.BytesPerSector do begin if i=1 then Grid1.Cells[0,j]:=IntToHex(((j-1)*16+(i-1)),3); Grid1.Cells[i,j]:=IntToHex(Buffer[k],2); inc(k); inc(i); if i>16 then begin i:=1; j:=j+1; Grid1.RowCount:= Grid1.RowCount+1; end; end; // расшифровка данных BPB for i:= 1 to 3 do s:=s+ intToHex(buffer[i],2); bpbList.Cells[1,1]:= s + 'h'; s:=''; // чтение имени ОС for i:= 4 to 4 + 7 do s:=s+ chr(buffer[i]); bpbList.Cells[1,2]:= s; s:=''; //-------------------------- bpbList.Cells[1,3]:=IntToStr(buffer[$C+1] shl 8 + buffer[$C]); bpbList.Cells[1,4]:=IntToStr(buffer[$C + 2]); bpbList.Cells[1,5]:=intToStr(buffer[$C + 4] shl 8 + buffer[$C+3]); bpbList.Cells[1,6]:=intToStr(buffer[$C+5]); bpbList.Cells[1,7]:=IntToStr(buffer[$F + 4] shl 8 + buffer[$F + 3]); bpbList.Cells[1,8]:=intToStr(buffer[$F+6] shl 8 + buffer[$F + 5]); bpbList.Cells[1,9]:=intToHex(buffer [22],2); if bpbList.Cells[1,9] = 'F8' then bpbList.Cells[1,9]:='Системный носитель инФормации' else if bpbList.Cells[1,9] = 'FDh' then bpbList.Cells[1,9]:=' накопитель - 2 стороны, 9 секторов' else if bpbList.Cells[1,9] = 'F9h' then bpbList.Cells[1,9]:=' накопитель - 2 стороны, 9 секторов' else if bpbList.Cells[1,9] = 'F0h' then bpbList.Cells[1,9]:=' накопитель - 2 стороны, 15 секторов'; bpbList.Cells[1,10]:=intToStr(buffer[$F+9] shl 8 + buffer[$F+8]); bpbList.Cells[1,11]:=intToStr(buffer[$F+11] shl 8 + buffer[$F+10]); bpbList.Cells[1,12]:=intToStr(buffer[$F+13] shl 8 + buffer[$F+12]); bpbList.Cells[1,13]:=intToStr(buffer[$F+17] shl 32 + buffer[$f+16]+ buffer[$f+15]+buffer[$f+14]); bpbList.Cells[1,14]:=intToStr(buffer[$F + 21] shl 24 + buffer[$F + 20] shl 16 + buffer[$F + 19] shl 8 + buffer[$F + 18]); bpbList.Cells[1,15]:=intToStr(buffer[$C + 25]); bpbList.Cells[1,16]:=intToStr(buffer[$F + 23]); bpbList.Cells[1,17]:=intToStr(buffer[$F + 24]); bpbList.Cells[1,18]:=intToHex((buffer[$F + 28] shl 24 + buffer[$F + 27] shl 16 + buffer[$F + 26] shl 8 + buffer[$F + 25]),8); //-----------вывод метки ----------- s:=''; for i:=29 to 40 do s:=s+chr(buffer[$F+i]); bpbList.Cells[1,19]:= s; s:=''; //---------------------------------- //-- чтение ID ОС------------- for i:= 55 to 62 do s:=s+ chr(buffer[i]); bpbList.Cells[1,20]:= s; s:=''; //---------------------------- end else ShowMessage('Не удалось считать блок параметров Bios'); end; // чтение данных из структуры DriveInfo procedure TForm3.Button3Click(Sender: TObject); var i,j,k:integer; read:Cardinal; s:string; buffer: array[1..131072] of byte; begin Memo2.Clear; if ReadSectors(hMBRDrive,0,1,@buffer,DiscGeometry.BytesPerSector) = DiscGeometry.BytesPerSector then begin for i:= 1 to 16 do Grid2.Cells[i,0]:=intToHex((i-1),1); i:=1; j:=1; k:=1; while k<=DiscGeometry.BytesPerSector do begin if i=1 then Grid2.Cells[0,j]:=IntToHex(((j-1)*16+(i-1)),3); Grid2.Cells[i,j]:=IntToHex(Buffer[k],2); inc(k); inc(i); if i>16 then begin i:=1; j:=j+1; Grid2.RowCount:= Grid2.RowCount+1; end; end; // Расшифровка PartitionTable // первая часть Memo2.Text:=Memo2.Text+'Первый элемент таблицы разделов системного диска: '+#13#10; Memo2.Text:=Memo2.Text+'Признак загрузки: '+intToHex(buffer[$1bf],2)+#13#10; Memo2.Text:=Memo2.Text+'Начало раздела диска{'; Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[448]); Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[449]); Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[450]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Тип раздела {'; Memo2.Text:=Memo2.Text+'Ос: '+intToStr(buffer[451]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Конец раздела диска{'; Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[$1c4]); Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[$1c5]); Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[$1c6]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Номер Сектора {'; Memo2.Text:=Memo2.Text+': '+intToStr(buffer[458]shl 32+buffer[457]+buffer[456]+buffer[455]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Размер раздела {'; Memo2.Text:=Memo2.Text+': '+intToStr(buffer[462]shl 24 +buffer[461] shl 16 +buffer[460]shl 8+buffer[459]); Memo2.Text:=Memo2.Text+' }'+#13#10+#13#10+#13#10; //вторая часть Memo2.Text:=Memo2.Text+'Второй элемент таблицы разделов системного диска: '+#13#10; Memo2.Text:=Memo2.Text+'Признак загрузки: '+intToHex(buffer[$1CF],2)+#13#10; Memo2.Text:=Memo2.Text+'Начало раздела диска{'; Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[465]); Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[466]); Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[467]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Тип раздела {'; Memo2.Text:=Memo2.Text+'Ос: '+intToStr(buffer[468]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Конец раздела диска{'; Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[469]); Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[470]); Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[471]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Номер Сектора {'; Memo2.Text:=Memo2.Text+': '+intToStr(buffer[$1D7+3]shl 24+buffer[$1D7+2] shl 16+buffer[$1D7+1]shl 8 +buffer[$1D7]); Memo2.Text:=Memo2.Text+' }'+#13#10; Memo2.Text:=Memo2.Text+'Размер раздела {'; Memo2.Text:=Memo2.Text+': '+intToStr(buffer[$1db+3]shl 24 +buffer[$11db+2] shl 16 +buffer[$1db+1]shl 8+buffer[$1db]); Memo2.Text:=Memo2.Text+' }'+#13#10+#13#10+#13#10; end else ShowMessage('Не удалось считать PartitionTable'); end; // получение инфо о нужных дисках procedure TForm3.FormActivate(Sender: TObject); var S,SOut : String; i:Integer; VolumeName,FileSystemName,NewDiscNumber : String; MaxComponentLength,FileSystemFlags:LongWord; // от переменной VolumeSerialNo : DWord; begin S:=GetDisks(DiskHDD); {Получаем список Жёстких дисков (Параметр DiskHDD)} s:=s+GetDisks(DiskFDD); s:=s+GetDisks(DiskNet); s:=s+GetDisks(DiskCDROM); s:=s+GetDisks(DiskRAM); SOut:=''; For i:=1 to Length(S) do {Получаем информацию о всех дисках и пишем в TLabel на форме} begin {Если диск существует/вставлен ...} if GetHDDInfo(S[I], VolumeName, FileSystemName,NewDiscNumber, MaxComponentLength, FileSystemFlags) then {... тогда собираем информацию} SOut:=SOut+ 'Диск: '+S[I]+#13#10+ 'Метка: '+VolumeName+#13#10+ 'Файловая система: '+FileSystemName+#13+#10+ 'Серийный номер: '+NewDiscNumber+#13+#10+ 'Макс. длина имени файла: '+IntToStr(MaxComponentLength)+#13+#10+ 'Flags: '+IntToHex(FileSystemFlags,4)+#13#10+#13#10; end; Disks.Caption:=SOut; {Выводим в компонент TLabel полученные данные о дисках} end; end. 5) Модуль ThrdRcvr (модуль описывающий работу потока – приёмника сообщений): unit ThrdRcvr; // принимающий поток interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls, Buttons, Menus, ComCtrls, ActnMan, ActnColorMaps; type TThreadReceiver = class(TThread) private PBaseAdress:PChar; TextString:String; nlineSize:integer; protected procedure Execute; override; public end; implementation uses Unit1; // Считываем соержимое из проекции файла в Memo1 procedure TThreadReceiver.Execute; begin while (not terminated) do begin WaitForSingleObject(Form1.HEvent, INFINITE); ResetEvent(Form1.HEvent); try // резерв. память в потоке для этотой проекции PBaseAdress:=MapViewOfFile(Form1.HFileSender, FILE_MAP_READ,0,0,65536); if (PBaseAdress = nil) then begin CloseHandle(Form1.HFileSender); st:='не удалось отобразить файл на адресное пространство'; Application.MessageBox(st,'Сообщение...',MB_OK); form1.BitBtn2.Visible:=false; form1.Button1.Visible:=false; exit; end; nlineSize:=integer(PBaseAdress^); SetLength(TextString,nlineSize); CopyMemory(PChar(TextString),Pointer(Integer(PBaseAdress)+4),nlineSize); Form1.Memo1.Text:=Form1.Memo1.Text+'---------'+#13#10; Form1.Memo1.Text:=Form1.Memo1.Text+TextString+#13#10; sendmessage(Form1.memo1.handle, em_linescroll, 0, Form1.memo1.lines.count-1); UnmapViewOfFile(PBaseAdress); finally end; end; end; end. 6) Модуль HDDInfo (модуль получающий информацию о жёстких дисках): unit HDDInfo; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, FileCtrl, ExtCtrls, Grids, ValEdit; const {Константы для TypeOfDisk функции GetDisks}DiskUnknown=0; {Неизвестные диски} DiskNone=1; {Отсутствующие диски} DiskFDD=DRIVE_REMOVABLE; {Съёмные диски, дискеты} DiskHDD=DRIVE_FIXED; {Не съёиные диски, жёсткие диски} DiskNet=DRIVE_REMOTE; {Сетевые диски} DiskCDROM=DRIVE_CDROM; {CD ROM} DiskRAM=DRIVE_RAMDISK; {Диски в ОЗУ} function GetDisks(TypeOfDisk : Word) : String; function GetHDDInfo(Disk : Char;Var VolumeName, FileSystemName,NewDiscNumber : String; MaxComponentLength, FileSystemFlags:LongWord) : Boolean; implementation //получить имена доступных дисков function GetDisks(TypeOfDisk : Word) : String;{Получить имена нужных дисков} var DriveArray : array[1..26] of Char; i:integer; beginDriveArray:='ABCDEFGHIJKLMNOPQRSTUVWXYZ'; for i:= 1 to 26 do if GetDriveType(PChar(DriveArray[I]+':\')) = TypeOfDisk then Result := Result+DriveArray[I]; end; // определение правильного серийного номера диска function GetReplaceCDNumber(num: String): String; var i, len: Integer; begin Result:= ''; len:= Length(num); if len <> 8 then exit; for i:= 1 to (len div 2) do begin Dec(len); Result:= Result + num[len]; Result:= Result + num[len+1]; Dec(len); end; end; // получить инфо о дисках с нужными именами function GetHDDInfo(Disk : Char;Var VolumeName, FileSystemName,NewDiscNumber : String; MaxComponentLength, FileSystemFlags:LongWord) : Boolean; var _VolumeName,_FileSystemName:array [0..MAX_PATH-1] of Char; _VolumeSerialNo,_MaxComponentLength,_FileSystemFlags:LongWord; _NewDiscNumber:string; begin if GetVolumeInformation(PChar(Disk+':\'),_VolumeName,MAX_PATH,@_VolumeSerialNo, _MaxComponentLength,_FileSystemFlags,_FileSystemName,MAX_PATH) then begin NewDiscNumber:=IntToHex(integer(_VolumeSerialNo),8); NewDiscNumber:=GetReplaceCDNumber(NewDiscNumber); VolumeName:=_VolumeName; MaxComponentLength:=_MaxComponentLength; FileSystemFlags:=_FileSystemFlags; FileSystemName:=_FileSystemName; Result:=True; end else Result:=False; end; end. Список литературы:1) М. Фленов «Библия Delphi» 2) А. Танцер «Синхронизация процессов при работе с Windows» 3) Сайт CitForum > http://citforum.ru/programming/delphi/disk_editor/ </ 4)Cайт Delphi-Faq > http://delphi-faq.zoxt.net/a79.htm <. 5) Cайт DelphiSource. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|