Федеральное агентство по образованию
Пензенский государственный университет
Кафедра «Информационной безопасности систем и технологий»
Пояснительная записка к курсовой работе
по теме:
«Системное программирование в операционных системах»
Дисциплина: Безопасность операционных систем
Группа
Выполнил:.
Проект принят с оценкой
Руководитель проекта:
Пенза, 2006 г.
Реферат
Пояснительная записка содержит 38с., 7 рис., 2 источника, 2прил.
VISUAL СИ++, ПРОГРАММА, РАСПИСАНИЕ, WINDOWSNT(98), ФАЙЛ.
Объектом исследования является системное программирование воперационных системах.
Целью работы является разработка программы, выполняющейзапуск программ по расписанию: расписание хранится в файле.
В процессе работы были освоены навыки системногопрограммирования в операционных системах.
В результате работы была разработана программа, выполняющаязапуск программ по расписанию: расписание хранится в файле (её текст приведён вприложении).
Содержание
1 Интерфейс
1.1 Понятие интерфейса и его назначение
1.2 Выбор интерфейса
2. Разработка алгоритма программы
3. Создание программы на базе разработанного алгоритма
4. Руководство пользователя
Заключение
Список использованных источников
Алгоритм программы
1 Интерфейс1.1 Понятие интерфейса и его назначение
Перед началом самого программирования и даже составленияалгоритмов необходимо представить себе как будет работать программа и посредствомэтого выбрать интерфейс.
Под интерфейсом понимают совокупность схемотехническихсредств и правил, обеспечивающих непосредственное взаимодействие составныхэлементов вычислительной системы и или программ. Интерфейс обеспечиваетвзаимосвязь между функциональными блоками или устройствами системы.
Основным назначением интерфейса является унификациявнутрисистемных и межсистемных связей и устройств сопряжения с целью эффективнойреализации прогрессивных методов проектирования функциональных элементоввычислительной системы.
Системный подход при проектировании представляет собой комплексное,взаимосвязанное, пропорциональное рассмотрение всех факторов, путей и методоврешения сложной многофакторной и многовариантной задачи проектированияинтерфейса взаимодействия. В отличие от классического инженерно — техническогопроектирования при использовании системного подхода учитываются все факторыпроектируемой системы — функциональные, психологические, социальные и дажеэстетические.
Автоматизация управления неизбежно влечёт за собойосуществление системного подхода, т.к. она предполагает наличиесаморегулирующейся системы, обладающей входами, выходами и механизмомуправления. Уже само понятие системы взаимодействия указывает на необходимостьрассмотрения окружающей среды, в которой она должна функционировать.
Таким образом, система взаимодействия должна рассматриватьсякак часть более обширной системы — АСУ реального времени, тогда как последняя — системы управляемой среды.
В настоящее время можно считать доказанным, что главнаязадача проектирования интерфейса пользователя заключается не в том, чтобы рационально«вписать» человека в контур управления, а в том, чтобы, исходя иззадач управления объектом, разработать систему взаимодействия двух равноправныхпартнёров (человек — оператор и аппаратно — программный комплекс АСУ),рационально управляющих объектом управления.1.2 Выбор интерфейса
Интерфейс взаимодействия с пользователем является важнымэлементом любой программы. От его продуманности и удобства часто зависит коммерческийуспех программного продукта.
Интерфейс пользователя можно разделить на пакетный иинтерактивные. Пакетные характеризуются тем, что пользователь долженсформировать пакет с заданиями, затем программа эти задания выполняет и выдаётрезультат. Интерактивные характеризуются тем, что пользователь в ходе работыпрограммы постоянно с ней взаимодействует. Существует интерфейс на базе меню,псевдографический интерфейс, интерактивно — командный интерфейс, эти интерфейсыописывать не будем, так как программа, которую необходимо создать по заданиютребует графический интерфейс. Графический интерфейс следует выбирать толькодля многомодульных программ, которые, предположительно будут иметь массовоеприменение.
В соответствии с заданием и для большего удобства и понятияпринципа работы программы интерфейс должен содержать наименьшее количествокнопок. Вследствие чего выберем: 1 поле, в котором будет вводиться имя файла срасписанием, одну кнопку после нажатия, которой будет происходить запускпрограмм, кнопку для приостановления работы, копку обзора, а также кнопку выход.Данная разработка представлена на рисунке 1./> /> /> /> /> /> /> /> /> /> /> /> /> /> /> />
Обзор /> /> />
Остановить работу /> />
Выход />
Файл с расписанием
Рисунок 1. Интерфейс программы.
2. Разработка алгоритма программы
В данном разделе проводится разработка алгоритма работыпрограммы, выполняющей запуск программ по расписанию, расписание которыххраниться в файле.
Прежде чем начать разработку, вводим несколько ограничений:
а) Общие требования к программе:
исходные данные должны храниться в файле;
программа должна обеспечивать взаимодействие с пользователемпосредством графического интерфейса;
процесс выполнения запуска программ должен быть реализован винтегрированной среде разработки Microsoft Visual C++ v.6.0.
б) Требования к организации файловых операций:
обеспечить возможность задания любого имени для файла срасписанием;
обеспечить обработку ошибочных ситуаций при работе с файломс выдачей соответствующих информационных сообщений пользователю.
программа должна быть организованна в виде приложения.
в) Дополнительное требование:
в файле с расписанием имя программы должно быть указанополностью и заключено в кавычки, а далее через пробел должно быть указано времяформата 00: 00: 00;
расписание может быть организовано и не по возрастанию;
После запуска программы пользователь должен будет ввести имяфайла с расписанием. После нажатия клавиши “Установить расписание” программадолжна будет проверить существование данного файла, если произошла ошибка, будетвыдаваться об этом сообщение пользователю. После открытия файла программа будетсчитывать строчку за строчкой, в которых будет храниться имена и время запускаемыхпрограмм и происходить проверка на их существование. Далее должна будетпроисходить проверка на окончание файла.
После завершения работы программы должен выдаваться отчёт о еёсостоянии.
Структурная схема алгоритма программы, выполняющей запускпрограмм по расписанию, расписание которых храниться в файле, приведена вприложении А.
3. Создание программы на базе разработанногоалгоритма
В данном разделе приводится описание текста программывыполняющей генерацию паролей пользователей. Данная программа реализована наязыке программирования С++ при помощи интегрированной среды обработки Visual С++.
Основные принципы работы графических приложений Windows.
В отличие от программ MS-DOS, графическая программа Windowsпосле запуска находится в «пассивном» состоянии. Она постоянноожидает от операционной системы управляющих данных, которые называютсясообщениями. Сообщения могут быть разного типа, например сообщение о нажатииклавиши, сообщение о движении курсора «мыши», управляющее сообщениеоперационной системы и т.д. Таким образом, работа графического приложениязаключается в следующем: вначале программа должна сформировать на экранеглавное окно программы. Весь вывод программа будет осуществлять в дальнейшем вэто окно в графическом виде. Затем программа должна включиться в обработкусообщений, которые посылает ей операционная система. Результат обработкисообщений может отображаться в главном окне программы.
Любое графическое приложение Windowsимеет типовую структуру, основой которой является каркасное приложение. Этоприложение содержит минимально необходимый программный код для обеспеченияфункционирования полноценного Windows-приложения.
Каркасное графическое приложение Windows.
Минимальное каркасное приложение Windowsсостоит из трех частей:
главной функции;
цикла обработки сообщений;
оконной функции.
Выполнение любого графического приложения начинается сглавной функции, имеющей обязательное имя WinMain (). Онасодержит код, осуществляющий инициализацию приложения в среде Windows.Видимым результатом работы функции является появление на экране графическогообъекта в виде окна. Последним действием кода главной функции является созданиецикла обработки сообщений. После его создания приложение становится пассивным иначинает взаимодействовать с операционной системой посредством сообщений. Обработкапоступающих сообщений осуществляется специальной функцией, называемой оконной.Особенность оконной функции заключается в том, что она вызывается изоперационной системы, а не из приложения, ее содержащего.
Для создания каркасного приложения в MS Visual C++ 6.0 необходимо создать новый проект, используя меню «File — >New‑>Projects‑>Win32 Application».Далее из предложенных вариантов необходимо выбрать«A simple Win32 application». В этом случае будет созданоприложение с пустой главной функцией. Для создания каркасного приложения в эту функциюнеобходимо добавить код инициализации окна программы и цикл обработки сообщений.Кроме того, в приложение необходимо добавить код оконной функции.
Главная функция имеет четыре параметра. Первый параметрявляется идентификатором данной программы, второй параметр всегда имеетзначение NULL, третий параметр содержит команднуюстроку, с помощью которой программа была запущена, а четвертый параметрсодержит информацию о том, как будет отображаться окно программы.
Оконная функция может иметь произвольное имя, но типвозвращаемого результата и количество и тип передаваемых параметров для неестрого определены. Прототип оконной функции должен выглядеть так:
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAMwParam, LPARAM lParam)
Где первый параметр — идентификатор окна, котороеобслуживается данной оконной функцией, второй параметр — идентификаторсообщения операционной системы, которое передается на обслуживание, третий ичетвертый параметры — дополнительные данные, передаваемые вместе с сообщением. Обычнопрототип оконной функции записывают в начале программы, до функции WinMain (), а сам код функции помещают в конец программы. Этоделается потому, что функция должна быть определена до ее использования в WinMain ().
Таким образом, первым шагом, создания каркасного приложениябудет определение прототипа оконной функции в начале программы (до функции WinMain).
Вторым шагом создания каркасного приложения будет создание иинициализация структуры с информацией класса окна. Для этого необходимо вфункции WinMain объявить переменную данного типа изаполнить все десять полей структуры:
WNDCLASS wcl;
// объявление переменной типа структуры класса окна
wcl. style=CS_HREDRAW|CS_VREDRAW;
// стиль окна. В данном случае показывает, что окно // будетперерисовываться при изменении горизонтального // и вертикального размеров.
wcl. lpfnWndProc=WindowProc;
// указатель на оконную функцию, которая будет // вызыватьсяоперационной системой для данного окна.
wcl. cbClsExtra=0;
// количество дополнительных байт для следующей // структуры.
wcl. cbWndExtra=0;
// количество дополнительных байт для следующего окна.
wcl. hInstance=hInstance;
// идентификатор процедуры (программы), владеющей // даннымокном.
wcl. hIcon=LoadIcon (NULL, IDI_APPLICATION);
// идентификатор класса значка (иконки) для данного // окна.Значок включается в проект в виде ресурса. В // данном случае функцией LoadIcon () загружается // стандартный значок для приложений Windows.
wcl. hCursor=LoadCursor (NULL, IDC_ARROW);
// идентификатор класса курсора для данного окна. Курсор // включаетсяв проект в виде ресурса. В данном случае // функцией LoadCursor() загружается стандартный курсор // в виде стрелки.
wcl. hbrBackground= (HBRUSH) GetStockObject(WHITE_BRUSH);
// идентификатор класса кисти для фона окна. В данном // случаеиспользуется белый цвет фона.
wcl. lpszMenuName=”MENU”;
// указатель на строку, идентифицирующую ресурс главного //меню окна.
wcl. lpszClassName=«Pass»;
// имя класса окна
Третьим шагом является создание окна. Он состоит изрегистрации класса окна, создания окна, показа и перерисовки окна. Регистрациякласса окна выполняется функцией RegisterClass ():
if (! RegisterClass (&wcl)) return 0;
В качестве параметра функции используется указатель назаполненную структуру класса окна. В случае успешной регистрации функциявозвращает ненулевой результат. В противном случае функция возвращает ноль иприложение необходимо завершить.
Создание окна выполняется функцией CreateWindow(), имеющей прототип
HWND CreateWindow (
LPCTSTR lpClassName, // адрес имени зарегистрированногокласса
LPCTSTR lpWindowName, // адрес имени окна
DWORD dwStyle, // стиль окна, константы WS_xxxxxx
int x, // горизонтальная позиция окна
int y, // вертикальная позиция окна
int nWidth, // ширина окна
int nHeight, // высота окна
HWND hWndParent, // идентификатор «внешнего» окна
HMENU hMenu, // идентификатор меню окна
HANDLE hInstance, // идентификатор приложения
LPVOID lpParam // адрес дополнительных данных
);
Функция возвращает идентификатор открытого окна.
В данном случае в функцию WinMainможно добавить такую строку:
HWND hWnd = CreateWindow (wcl. lpszClassName,«Window», WS_OVERLAPPEDWINDOW, // окно с заголовком и бордюром CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, // положение и размер «поумолчанию» NULL, NULL, hInstance, NULL);
// нет «внешнего» окна (это главное окно программы),
// используется меню класса окна,
// идентификатор программы — второй параметр функции WinMain ()
// нет дополнительных данных.
Далее, для показа окна на экране, используется функция ShowWindow ():
ShowWindow (hWnd, nCmdShow);
Где первый параметр — идентификатор окна (которое должнобыть уже зарегистрировано и открыто), а второй параметр — способ отображенияокна. В качестве второго параметра используется способ отображения, переданныйоперационной системой функции WinMain (четвертыйпараметр).
И, наконец, для перерисовки окна используется функция UpdateWindow ():
UpdateWindow (hWnd);
В которую в качестве параметра передается идентификатор окна.
Четвертым шагом создания каркасного приложения будетсоздание цикла обработки сообщений:
MSG lpMsg;
while (GetMessage (&lpMsg, NULL, 0,0))
{
TranslateMessage (&lpMsg);
DispatchMessage (&lpMsg);
}
return lpMsg. wParam;
Функция GetMessage () выбираетсообщение из очереди сообщений и помещает его в структуру, адрес которой указанв качестве первого параметра. Функция работает только с сообщениями,адресованными данному приложению или его дочерним процессам. Данная функциявозвращает 0, если было выбрано сообщение WM_QUIT и не ноль во всех остальных случаях. Таким образом, циклобработки сообщений завершается после получения сообщения WM_QUIT. А затем завершается и сама функция WinMain().
Минимальный цикл обработки сообщений должен состоять извызова системной функции DispatchMessage (), котораяпередает сообщение оконной функции, связанной с данным окном. Перед вызовомфункции DispatchMessage () сообщение может подвергатьсяобработке. Так, функция TranslateMessage преобразуетсообщения от клавиатуры. В Windows от клавиатуры идутсообщения WM_KEYDOUN и WM_KEYUP, соответствующие нажатию иотпусканию клавиш. Эти сообщения содержат виртуальные коды клавиш. Функция TranslateMessage () преобразует эти сообщения в сообщения WM_CHAR, содержащие Пятым, ипоследним, шагом создания каркасного приложения является написание оконнойфункции. Она выглядит так:
LRESULT CALLBACK WindowProc (HWND hWnd,UINTmessage,WPARAM wParam,LPARAM lParam)
{
static HINSTANCE hInstance;
switch (message)
{
case WM_CREATE:
{
hInstance = ( (LPCREATESTRUCT) lParam) — >hInstance;
DialogBox (hInstance, IDD_DIAL,hWnd,MyDlgProc);
break;
}
case WM_DESTROY:
{
PostQuitMessage (0);
break;
}
default:
return DefWindowProc (hWnd, message,wParam, lParam);
}
return 0;
}
Оконная процедура получает сообщение и анализирует его. Послеанализа сообщение либо обрабатывается, либо передает сообщение процедуреобработки сообщений по умолчанию. Например оконная функция обрабатываетсообщение — WM_DESTROY. Этосообщение передается оконной функции при закрытии окна. Нормальной реакцией натакое сообщение является посылка сообщения WM_QUIT для завершения приложения. Это сообщение посылаетсяпутем вызова функции PostQuitMessage (). Параметромэтой функции является код завершения программы.
Таким образом получено минимальное каркасное приложение Windows.
Создание меню.
Для добавления меню к программе необходимо создатьсоответствующий ресурс. Для создания ресурса меню в проекте необходимовоспользоваться пунктом меню «Insert — > Resourse — > Resurs Type: Menu — > New». При этом в окне редактора появится возможностьв интерактивном режиме создать систему меню. Для редактирования свойствэлементов меню можно использовать «View‑>Properties». Каждому пункту меню необходимо присвоитьсвой идентификатор. После завершения создания ресурса необходимо его сохранить.При этом автоматически будут созданы два файла — resource.h и script. rc(где script — имя файла ресурсаd). После этого необходимо файл ресурса script.rc включить в проект в папку Source Files, а в файл StdAfh.h включить строку #include"resource. h".После того, как файл ресурса будет включен в проект, в окне проекта станет,доступна закладка ResourceView. Используя эту закладкуможно просмотреть древовидную структуру ресурсов проекта. В папке menu будут показаны идентификаторы ресурсов меню.
Для того чтобы созданное меню отображалось в окне программыего надо указать при инициализации структуры класса окна:
wcl. lpszMenuName=“MENU”;
где “MENU" — выбранный мноюидентификатор меню. После компиляции такого проекта в окне программы будетотображаться меню.
Для того, чтобы назначить пунктам меню конкретные действия,необходимо включить их в обработку оконной функцией. Выбор пунктов меню спомощью мыши отслеживается автоматически операционной системой и формируютсясообщения WM_COMMAND. Вкачестве параметра такого сообщения передается идентификатор выбранного пунктаменю. Таким образом, в оконной функции необходимо перехватить сообщение типа WM_COMMAND и проверить его параметр. Адалее, в зависимости от параметра, выполнить то или иное действие.
Следует отметить, что используемые переменные следуетобъявить вне тела оператора switch.
Вывод сообщений в отдельном окне.
Самым простым способом вывода сообщений в отдельном окнеявляется использование функции MessageBox (). Этафункция имеет следующий формат:
int MessageBox (
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType);
Где параметры имеют следующее значение:
hWnd — идентификатор окна-владельцасоздаваемого окна с сообщением;
lpText — указатель на строку с сообщением, строка должназаканчиваться символом с кодом 0;
lpCaption — указатель на строку с заголовком окна, строкадолжна заканчиваться символом с кодом 0;
uType — тип окна с сообщением, может быть комбинациейразличных констант.д.опустимы следующие константы в этом параметре:
MB_YESNO — окно будет иметь две кнопки: Yes и No.
MB_YESNOCANCEL — окно будет иметь три кнопки: Yes, No, иCancel.
Функция возвращает ноль в случае нехватки памяти дляоткрытия окна. При успешном завершении функции она возвращает одно из следующихзначений:
IDABORT — выбрана кнопка Abort.
IDCANCEL — выбрана кнопка Cancel.
IDIGNORE — выбрана кнопка Ignore.
IDNO — выбрана кнопка No.
IDOK — выбрана кнопка OK.
IDRETRY — выбрана кнопка Retry.
IDYES — выбрана кнопка Yes.
Если окно содержит кнопку Cancel, то функция возвращаетзначение IDCANCEL в случае нажатия клавиши ESC или выбора кнопки Cancel. Есликнопка Cancel отсутствует, то нажатие клавиши ESC не имеет эффекта.
На этом создание программы на языке Си закончилось.
Создание процесса.
"Процесс — это выполняющееся приложение, котороесостоит из личного виртуального адресного пространства, кода, данных и другихресурсов операционной системы, таких как файлы, пайпы и синхронизационныеобъекты, видимые для процесса."
У процесса есть несколько объектов: адресное пространство,выполняемый модуль (модули) и все, что эти модули создают или открывают. Какминимум, процесс должен состоять из выполняющегося модуля, личного адресногопространства и ветви. У каждого процесса по крайней мере одна ветвь. Что такоеветвь? Фактически, ветвь — это выполняющаяся очередь. Когда Windows впервыесоздает процесс, она делает только одну ветвь на процесс. Эта ветвь обычноначинает выполнение с первой инструкции в модуле. Если в дальнейшем понадобитсябольше ветвей, он может сам создать их.
Когда Windows получает команду для создания процесса, онасоздает личное адресное пространство для процесса, а затем она загружаетисполняемый файл в пространство. После этого она создает основную ветвь дляпроцесса.
Под Win32 можно создать процессы из своих программ с помощьюфункции Createprocess. Она имеет следующих синтаксис:
BOOL CreateProcess (
LPCTSTR lpszApplicationName.
LPCTSTR IpszCommandLine,
LPSECURITYJUTRIBUTES ipsaProcess.
LPSECURITY_ATTRIBUTES lpsaThread,
BOOL flnhentHandles,
DWORD fdwCreate,
LPVOID ipvEnvironment.
LPTSTR lpszCurDir,
LPSTARTUPINFO ipsiStartlnfo,
LPPROCESS_INFORMATION lppiProcInfo):
Когда поток в приложении вызывает CreateProcess, системасоздает объект ядра «процесс» с начальным значением счетчика числаего пользователей, равным 1. Этот объект — не сам процесс, а компактнаяструктура данных, через которую операционная система управляет процессом. (Объектядра «процесс» следует рассматривать как структуру данных состатистической информацией о процессе) Затем система создает для новогопроцесса виртуальное адресное пространство размером 4 Гб и загружает в него коди данные как для исполняемого файла, так и для любых DLL (если таковыетребуются).
Далее система формирует объект ядра «поток» (сосчетчиком, равным 1) для первичного потока нового процесса. Как и в первомслучае, объект ядра «поток» — это компактная структура данных, черезкоторую система управляет потоком. Первичный поток начнет с исполнениястартового кода из стандартной библиотеки С, который — как всегда — вызоветфункцию WinMain. Если системе удастся создать новый процесс и его первичныйпоток, CreateProcess вернет TRUE.
На этом программирование закончилось.
4. Руководство пользователя
Для начала работы с программой необходимо записать файл срасписанием следующего формата «C: /totalcmd/TOTALCMD. EXE» 00: 00: 00
Далее необходимо запустить файл с названием OSkurs. Послезапуска появится окно которое представлено на рис.10.
/>
Рисунок 2.
Далее необходимо ввести в окошко полное имя файла в которомнаходится расписание и нажать на клавишу “Установить расписание”. После чегобудет происходить запуск программ по расписанию. Если имя не будет указано, топоявится окошко:
/>
Рисунок 3.
Если данного файла не существует или имя указано не верно товыдаётся сообщение.
/>
Рисунок 4
Если файл с расписанием записан не верно, то выдаётсясообщение:
/>
Рисунок 5
Если имя программы указано с ошибкой или его не существует,то выдаётся сообщение и два варианта продолжения работы программы:
/>
Рисунок 6.
После успешного окончания работы программы выдаётсясообщение:
/>
Рисунок 7.
Для завершения расписания необходимо нажать на клавишу“Остановить работу". Для выхода из программы необходимо нажать на клавишу“Выход” или нажав на “крестик".
Заключение
В процессе выполнения курсового проекта была разработана программа,выполняющая запуск программ по расписанию, расписание хранится в файле. Программабыла написана при помощи интегрированной среды разработки Visual C++. Программа соответствует всемфункциональным требованиям, заданным на курсовое проектирование. Взаимодействиес пользователем осуществляется с помощью графического интерфейса.
Таким образом, задание на курсовое проектирование былополностью выполнено.
Список использованных источников
1. Келецкий Я. Энциклопедия языкаСи/ Пер. с англ. — М.: Мир, 1992. — 687с.
2. Керниган Б., Ричи Д., Фьюер А. Языкпрограммирования Си. Задачи по языку С / Пер. с англ. — М.: Финансы истатистика, 1985. — 279с.
Алгоритм программы
Приложение А
/>
— [на лист 2
Рисунок А.1. Алгоритм программы
/>
— [слиста1
Рисунок А.1. Лист №2
Приложение Б
Текст программы
#include
#include «resource. h»
#include
#define WM_SHELLNOTIFY WM_USER+5
#define IDC_RESTORE 1000
#define TM 1001
typedef struct _SHEDULEDATA {
char fname [120] ;
char tname [6] ;
int h;
int m;
int s;
int priority;
int delay;
} SHEDULEDATA;
char * FileOpen (HWND hWnd);
int FindNext (SHEDULEDATA sd [30], intcount);
void cstrcpy (char *a,char *b, int from,int count);
void MakeItStandart (SHEDULEDATA sd [30], intcount);
void SubtDelay (SHEDULEDATA sd [30], intcount, int delay);
int ReadShedule (HANDLE hFile,SHEDULEDATAsd [30]);
LRESULT CALLBACK WindowProc (HWND hWnd,UINTmessage,WPARAM wParam,LPARAM lParam); // дескриптор окна
INT CALLBACK MyDlgProc (HWND hDlg, // обращаетсяк dialog box
UINT uMsg, // сообщение
WPARAM wParam, // первый параметр сообщения
LPARAM lParam // второй параметр сообщения);
int APIENTRY WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wcl;
HWND hWnd;
MSG lpMsg;
// заполнение структуры спараметрами окна программы
wcl. style=CS_HREDRAW|CS_VREDRAW; // стиль окна
wcl. lpfnWndProc=WindowProc; // ф-ция обработки событий окна // оконнаяпроцедура
wcl. cbClsExtra=0;// дополнительные байты класса
wcl. cbWndExtra=0;// дополнительные байты окна
wcl. hInstance=hInstance; // дескриптор экземпляра окна // дескрипторпиктограммы
wcl. hIcon=LoadIcon (NULL, IDI_APPLICATION);
wcl. hCursor=LoadCursor (NULL, IDC_ARROW);// дескриптор курсора
wcl. hbrBackground= (HBRUSH) GetStockObject(WHITE_BRUSH);); // цвет фона
wcl. lpszMenuName=NULL; // имя ресурса с главным меню программы // ресурс меню,связанный с окном
wcl. lpszClassName=«Pass»; // имя класса окна
if (! RegisterClass (&wcl))
return 0;
hWnd=CreateWindow (wcl. lpszClassName,«window»,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow (hWnd,SW_HIDE);
UpdateWindow (hWnd);
while (GetMessage (&lpMsg, NULL, 0,0))
{
TranslateMessage (&lpMsg);
DispatchMessage (&lpMsg);
}
return lpMsg. wParam;
}
LRESULT CALLBACK WindowProc (HWND hWnd,UINTmessage,WPARAM wParam,LPARAM lParam) // дескриптор окна
{
static HINSTANCE hInstance;
switch (message)
{
case WM_CREATE:
{
hInstance = ( (LPCREATESTRUCT) lParam) — >hInstance;
DialogBox (hInstance, IDD_DIAL,hWnd,MyDlgProc);
break;
}
case WM_DESTROY:
{
PostQuitMessage (0);
break;
}
default:
return DefWindowProc (hWnd, message,wParam, lParam);
}
return 0;
}
INT CALLBACK MyDlgProc (HWND hDlg,UINTuMsg,WPARAM wParam,LPARAM lParam)
{
static SHEDULEDATA sd [30] ;
static int count,nextexe,delayexe;
static char name [300] ;
char * n;
static BOOL frst, fileopen =FALSE,filewasopened=FALSE;
BOOL cp;
char tip [] =«запуск по расписанию\0»;
UINT uId=111;
static NOTIFYICONDATA nfd;
int i;
static STARTUPINFO si;
static HANDLE hMenu,hTimer,hFile;
static PROCESS_INFORMATION pi;
switch (uMsg)
{
case WM_INITDIALOG:
{
si. cb=sizeof (STARTUPINFO);
GetStartupInfo (&si);
nfd. cbSize=sizeof (NOTIFYICONDATA);
nfd. hWnd=hDlg;
nfd. uID=uId;
nfd. uFlags=NIF_MESSAGE|NIF_TIP|NIF_ICON;
nfd. uCallbackMessage=WM_SHELLNOTIFY;
lstrcpy (nfd. szTip,tip);
nfd. hIcon=LoadIcon (NULL, IDI_WINLOGO);
hMenu = CreatePopupMenu ();
AppendMenu (hMenu,MF_ENABLED|MF_STRING, IDC_RESTORE,«восстановить»);
AppendMenu (hMenu,MF_ENABLED|MF_SEPARATOR,0,0);
AppendMenu (hMenu,MF_ENABLED|MF_STRING, IDC_EXIT,«закрыть»);
frst=TRUE;
SetDlgItemText (hDlg, IDC_TEXT,"");
return (TRUE);
}
case WM_CLOSE:
{
if (filewasopened)
CloseHandle (hFile);
Shell_NotifyIcon (NIM_DELETE,&nfd);
DestroyMenu (hMenu);
SendMessage (GetParent (hDlg),WM_DESTROY,0,0);
EndDialog (hDlg, 0);
return (TRUE);
}
case WM_SIZE:
{
if (wParam==SIZE_MINIMIZED)
{
ShowWindow (hDlg,SW_HIDE);
Shell_NotifyIcon (NIM_ADD,&nfd);
}
return TRUE;
}
case WM_TIMER:
{
cp=CreateProcess (sd [nextexe]. fname,NULL,NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,NULL,NULL,NULL,&si,&pi);
KillTimer (hDlg,TM);
if (! cp)
{
if (MessageBox(hDlg,«Приложение не удалось запустить. Продолжитьработу?»,sd [nextexe]. fname,MB_YESNO|MB_ICONERROR) ==IDNO)
SendMessage (hDlg,WM_COMMAND, IDC_STOP,0);
else
SendMessage (hDlg,WM_COMMAND, IDC_START,0);
}
else
{
nextexe=FindNext (sd,count);
if (nextexe
{
SendMessage (hDlg,WM_COMMAND, IDC_STOP,0);
return TRUE;
}
delayexe=sd [nextexe]. delay;
sd [nextexe]. delay=-1;
SubtDelay (sd,count,delayexe);
if (! SetTimer (hDlg,TM,1000*delayexe,NULL))
{
frst=TRUE;
if (MessageBox(hDlg,«В системе нет свободных таймеров. »,0,MB_RETRYCANCEL| MB_ICONERROR) ==IDRETRY)
SendMessage (hDlg,WM_COMMAND, IDC_START,0);
else
SendMessage (hDlg,WM_COMMAND, IDC_STOP,0);
}
}
return TRUE;
}
case WM_SHELLNOTIFY:
{
POINT pn;
if (wParam==uId)
{
if (lParam==WM_RBUTTONDOWN)
{
GetCursorPos (&pn);
SetForegroundWindow (hDlg);
TrackPopupMenu (hMenu,TPM_RIGHTALIGN,pn. x,pn.y,0,hDlg,NULL);
PostMessage (hDlg,WM_NULL,0,0);
}
else if (lParam==WM_LBUTTONDOWN)
SendMessage (hDlg,WM_COMMAND, IDC_RESTORE,0);
}
return TRUE;
}
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDC_EXIT:
{
if (filewasopened)
CloseHandle (hFile);
Shell_NotifyIcon (NIM_DELETE,&nfd);
DestroyMenu (hMenu);
SendMessage (GetParent (hDlg),WM_DESTROY,0,0);
EndDialog (hDlg,0);
return TRUE;
}
case IDC_OPEN:
{
n=FileOpen (hDlg);
if (n! =0)
{
lstrcpy (name,n);
fileopen=TRUE;
SetDlgItemText (hDlg, IDC_TEXT,name);
}
return TRUE;
}
case IDC_START:
{
if (frst)
{
if (! fileopen)
{
i=GetDlgItemText (hDlg, IDC_TEXT,name,120);
if (i==0)
{
MessageBox (hDlg,«введите имя файла с расписанием»,«ожидаетсяввод»,MB_OK);
return TRUE;
}
}
if ( (hFile=CreateFile (name,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL))==INVALID_HANDLE_VALUE)
MessageBox (0,«Не удается открытьфайл с расписанием»,«error»,MB_APPLMODAL|MB_OK|MB_ICONSTOP);
filewasopened=FALSE;
return TRUE;
}
filewasopened=TRUE;
count=ReadShedule (hFile,sd);
if (count
{
MessageBox (hDlg,«Файл не соответствуетформату»,NULL,MB_OK|MB_ICONERROR);
return TRUE;
}
CloseHandle (hFile);
MakeItStandart (sd,count);
filewasopened=frst=FALSE;
}
nextexe=FindNext (sd,count);
if (nextexe
{
SendMessage (hDlg,WM_COMMAND, IDC_STOP,0);
return TRUE;
}
delayexe=sd [nextexe]. delay;
sd [nextexe]. delay=-1;
SubtDelay (sd,count,delayexe);
SendMessage (hDlg,WM_SIZE,SIZE_MINIMIZED,0);
if (! SetTimer (hDlg,TM,1000*delayexe,NULL))
{
frst=TRUE;
if (MessageBox(hDlg,«В системе нет свободных таймеров. »,0,MB_RETRYCANCEL| MB_ICONERROR) ==IDRETRY)
SendMessage (hDlg,WM_COMMAND, IDC_START,0);
else
SendMessage (hDlg,WM_COMMAND, IDC_STOP,0);
}
return TRUE;
}
case IDC_STOP:
{
if (! frst)
{
KillTimer (hDlg,TM);
count =0;
nextexe=-1;
frst=TRUE;
MessageBox (hDlg,«в расписании большенет задач»,«Завершение»,MB_OK|MB_ICONINFORMATION);
}
return TRUE;
}
case IDC_RESTORE:
{
Shell_NotifyIcon (NIM_DELETE,&nfd);
ShowWindow (hDlg,SW_RESTORE);
SetForegroundWindow (hDlg);
return TRUE;
}
}
return TRUE;
}
return FALSE;
}
char * FileOpen (HWND hWnd)
{
OPENFILENAME filename;
char name [512] = "";
ZeroMemory (&filename, sizeof (filename));
filename. lStructSize = sizeof (filename);
filename. hwndOwner = hWnd;
filename. lpstrFile = name;
filename. lpstrFile [0] = '\0';
filename. nMaxFile = sizeof (name);
filename. lpstrFilter = «Text files\0*.txt\0»;
filename. nFilterIndex = 1;
filename. lpstrFileTitle = «Выберитеимя файла для сравнения… »;
filename. nMaxFileTitle = 0;
filename. lpstrInitialDir = NULL;
filename. Flags = OFN_PATHMUSTEXIST |OFN_FILEMUSTEXIST;
if (GetOpenFileName (&filename)! =NULL)
return (filename. lpstrFile);
else
return 0;
}
int ReadShedule (HANDLE hFile,SHEDULEDATA sd[30])
{
char str [200] ="";
char symb;
char buff [2] ="";
int w;
BOOL IsComm;
int numb;
int i;
int j;
for (i=0; i
{
j=-1;
w=0;
while (1)
{
ReadFile (hFile,&symb,1,&numb,NULL);
if (numb==0)
return i+1;
if (symb=='\\')
symb='/';
if ( (j==-1) && (symb! ='"'))
return — 1;
else
if (j==-1)
{
IsComm=TRUE;
j++;
continue;
}
else
if (IsComm)
if (symb=='"')
{
IsComm=FALSE;
sd [i]. fname [j] =0;
j=0;
continue;
}
else
{
sd [i]. fname [j] =symb;
j++;
continue;
}
else
if ( (symb==0xd) || (symb==' ') || (symb==':'))
continue;
if ( (symb! =0xa))
{
if (j>5)
return — 1;
sd [i]. tname [j] =symb;
j++;
continue;
}
else
break;
}
}
return i+1;
}
void cstrcpy (char *a,char *b, int from,int count)
{
int i;
int j=0;
for (i=from; i
{
b [j] =a [i] ;
j++;
}
}
void MakeItStandart (SHEDULEDATA sd [30], intcount)
{
int i;
SYSTEMTIME st;
char buffer [2] ;
int uis;
int uil;
int ui;
GetLocalTime (&st);
for (i=0; i
{
cstrcpy (sd [i]. tname,buffer,0,2);
sd [i]. h=atoi (buffer);
cstrcpy (sd [i]. tname,buffer,2,2);
sd [i]. m=atoi (buffer);
cstrcpy (sd [i]. tname,buffer,4,2);
sd [i]. s=atoi (buffer);
uil=sd [i]. h*3600+sd [i]. m*60+sd [i]. s;
uis=st. wHour*3600+st. wMinute*60+st. wSecond;
ui=uil-uis;
if (ui
sd [i]. delay=ui+24*3600;
else
sd [i]. delay=ui;
}
}
int FindNext (SHEDULEDATA sd [30], intcount)
{
int i,min=0xFFFFFFF;
int minnumber=-1;
for (i=0; i
{
if (sd [i]. delay
continue;
else
if (sd [i]. delay
{
min=sd [i]. delay;
minnumber=i;
}
}
return minnumber;
}
void SubtDelay (SHEDULEDATA sd [30], intcount, int delay)
{
int i;
for (i=0; i
if (sd [i]. delay>=0)
sd [i]. delay-=delay;
}