FoxIs, находящийся в каталоге Visual FoxPro ...\Samples\Servers\Foxisapi\FoxIs, иллюстрирует создание out-of-process .exe или in-process .dll с функциональностью ISAPI, к которому можно обращаться из Visual FoxPro, как самостоятельной программы, из клиентов автоматизации и из Web браузера. Изменения, которые вы сделаете в его классах, могут улучшить сервер автоматизации, вне зависимости от того, откуда он запущен.
Для того, чтобы открыть проект образца FoxIs
-
Напечатайте приведенную ниже команжу в окне Command:
Скопировать код
MODIFY PROJECT (HOME(2) + 'servers\foxisapi\foxis\foxis')
Запуск образца FoxIs
Вы можете запустить образец FoxIs четырьмя разными путями. Когда вы будете пробовать код, то в качестве неплохой идеи можете воспользоваться рекомендуемым порядком:
Запуск из Visual FoxPro
Для запуска образца FoxIs из Visual FoxPro, выполните последовательность приведенных ниже команд в окне Command.
![]() | |
---|---|
SET DEFAULT TO (HOME(2) + 'servers\foxisapi\foxis\') SET CLASSLIB TO employee ox = CREATEOBJECT('employee') ox.show |
Запуск в качестве независимого исполнимого приложения
Вы можете построить исполнимый файл из образца с помощью приведенной ниже строки кода:
![]() | |
---|---|
BUILD EXE foxis FROM foxis |
Скомпилированный файл, FOXIS.EXE, представляет из себя программу для Windows, которая может быть добавлена в Windows Start menu, запущена из Windows Explorer и тому подобным образом.
Запуск в качестве сервера автоматизации
Если FoxIs будет скомпилирован в .exe или в .dll, он регистрируется как сервер автоматизации в реестре Windows. Вы можете создать объект, основанный на классе employee из любого OLE контроллера, например, Excel, Visual Basic и Visual FoxPro:
![]() | |
---|---|
ox = CREATEOBJECT('foxis.employee') ox.SHOW |
Запуск из Web браузера
Вы можете даже запустить образец FoxIs из Web браузера, который может быть на другой машине, такой как 286 под MS-DOS, Unixe, Macintosh или Personal Digital Assistant.
Системные требования для использования через Internet
Для запуска образца FoxIs из Web браузера у вас должны быть запущены:
-
Windows 98 или Windows 2000 или более поздний.
-
ISAPI-совместимый Web сервер, такой как Microsoft Personal Web Server для Windows 98 или Microsoft Internet Information Services (IIS). IIS идет в поставке с Windows 2000 и более поздними версиями и может быть загружен с сайта www.microsoft.com; Personal Web Server также может быть загружен с сайта www.microsoft.com.
Если вы используете Windows 2000 или более позднюю версию, вам необходимо запустить утилиту DCOMCNFG, для конфигурирования DCOM с тем, чтобы обеспечить права сервису IIS на создание OLE объектов.
Для конфигурирования Windows 2000 или поздних DCOM
-
В окне Command операционной системы, не Visual FoxPro!!!, напечатайте DCOMCNFG м затем нажмите Enter.
-
На закладке Applications выберите имя сервера автоматизации. Когда вы компилировали сервер, ему по умолчанию было присвоено имя "employee".
-
На закладке Default Security диалогового блока Distributed COM Configuration Properties, выберите Edit Default для каждой области : Default Access Permissions, Default Launch Permissions и Default Configuration Permissions.
-
В появившемся диалоговом блоке Registry Value Permissions для каждой области выберите Add.
-
В боксе Add Names диалогового окна Add Users and Groups, впечатайте имя вашего WWW сервера и имя пользователя вашего входа (login user name).
Вы можете увидеть имя сервера в окне Microsoft Internet Service Manager Properties window. Если имя вашей машины - MINE, приведенная ниже строка в боксе Add Names установит пользователя по умолчанию:
Скопировать код
\MINE\IUSR_MINE
Если имя вашей машины - MINE и вы вошли как HOMER, то следующая строка в боксе Add Names установит разрешения для вас при входе:
Скопировать код
\MINE\HOMER
Установка образца FoxIs для доступа чере Internet
Для установки образца FoxIs, вам необходимо создать .exe или .dll из проекта FoxIs, и затем скопировать файл в ваш каталог Inetsvr\Scripts.
Для устоновки образца FoxIs
-
Откройте проект FOXIS.
-
Щелкните на кнопке Build и затем выберите Build COM DLL.
-
Скопируйте Foxisapi.dll в папку Inetsrv\Scripts.
Предварительное тестирование
Вы можете потестировать образец приложения FoxIs на различных уровнях для того, чтобы увидеть, что все сконфигурировано корректно.
Для того, чтобы видеть, что код работает
-
В меню Program выберите Do.
-
Выберите Main.prg в каталоге Visual FoxPro Samples\Servers\Foxisapi.
-
Выберите Do.
Для того, чтобы увидеть, что .EXE работает
-
В командном окне Visual FoxPro выдайте приведенную ниже команду:
Скопировать код
BUILD EXE Foxis.exe FROM foxis
-
Произведите двойной щелчок на Foxis.exe в Windows Explorer.
Для того, чтобы увидеть, что сервер автоматизации FoxIs работает
-
Выполните следующие команды:
Скопировать код
OX= CREATEOBJECT('FOXIS.EMPLOYEE') OX.Show && See if it works as a ISAPI Automation server ?OX.Startup( ) && See if it returns html
Намного легче протестировать сервер автоматизации из контроллера автоматизации, такого как Visual FoxPro до создания его в FoxIs.
Установка HTML страницы
Для того, чтобы этот предмет запустился, вам нужна HTML страница, которая содержит ссылку на URL. Например, возьмите приведенный ниже код и поместите его в файл Wwwroot\default.htm file.
![]() | |
---|---|
<a HREF="/scripts/foxisapi.dll/FoxIS.employee.startup"> <i>VFP ISAPI AUTOMATION SERVER DEMO PAGE</i> </a> |
Затем используйте браузер, который может быть на этой же машине и подсоединитесь к YourMachineName. Например, если имя вашей машины "myMachine," тогда напечайтайте "myMachine" как URL, на который нужно придти. Это выдаст страницу Default.htm page на сервере с именем "myMachine"
Инициализируется CreateObject("foxis.employee") и на объекте будет вызван метод Startup, который вернет сгенерированную страницу HTML. Если сервер автоматизации еще не построен, тогда Foxisapi.dll вернет HTML страницу с характерным для WEB кодом ошибки.
Затем используйте ваш Web браузер для обращения к приведенному выше href. Если вы получите HTML страницу с ошибкой, на которой говорится "Foxisapi error", тогда вы будете знать, что DLL загружена и работает.
![]() | |
---|---|
<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd"> <INPUT NAME="Cmd" VALUE = "Reset"> <INPUT TYPE="submit" VALUE="Dos Command"> </FORM> |
В действительности вы можете положить любую действительную команду MS-DOS и это будет выполнено на серверной машине. Если это команда "Reset" (по умолчанию), тогда это высвободит первую инстанцию ISAPI сервера автоматизации наравне с ним самим, таким образом полностью высвобождая сервер ISAPI.
Кроме того, вы можете оценить любое выражение Visual FoxPro. Однако, если выражение Visual FoxPro отображает модальный диалог, такой, какой к примеру производит функция MESSAGEBOX( ), сервер автоматизации зависнет в ожидании ответа, который не может быть предоставлен. Однако, для in-process .dll, модальный интерфейс обслуживается автоматически и сервер автоматизации не зависнет.
![]() | |
---|---|
<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd?FOXCMD"> <INPUT NAME="Cmd"> <INPUT TYPE="submit" VALUE="Fox Expression"> like "today is "+ cdow(date()) or 45 * 3 or SYS(2004) </FORM> |
Отладка сервера
Сервер Windows NT не имеет Desktop, поэтому на серверной машине не покажется интерфейс пользователя. Это означает, что вы должны отладить ваш сервер автоматиции до его развертывания.
Для трассироваки через Foxisapi.dll с помощью Visual C++ 5.0
-
Откройте Foxisapi.mak.
-
Удалите значок комментария из приведенной ниже строки кода в HttpExtensionProc:
Скопировать код
// _asm int 3
-
Перестройте проект.
-
Запустите MSDEV с идентификаторов процесса (PID) Inetinfo.exe. Вы можете получить идентификатор процесса в Windows Task Manager.
Этот процесс применяется к Windows 2000 или более поздней версии.
![]() |
---|
При отладке у вас не будет возможности выключить Web сервер для изменения сервера автоматизации. Вы можете просто прервать out-of-process компонент посылкой значения reset методу cmd, так как это описано выше, или, при использовании Win32 SDK с помощью TLIST, KILL, PVIEW или через Task Manager в Windows 2000 или более поздней версии. |
Класс ISForm
"Движок" oобразца представляет собой класс ISForm в Isapi.vcx.
Точки входа в классе ISForm
Приведенные ниже методы могут быть вызваны из Web браузера с помощью Foxisapi.dll, для возврата HTML страниц.
Метод | возвращает |
---|---|
Cmd |
вычисление выражения Visual FoxPro или результаты команд MS-DOS. |
DoSave |
сохраняет изменения, сделанные пользователем в данных и возвращает HTML страницу employee. |
Skipit |
информацию работника для указанного работника в таблице. Skipit берет информацию cookie посылаемую в качестве параметра из Web браузера, проверяет таблицу cookies с целью поиска предыдущего номера записи и смещает указатель записи вперед или назад относительно номера записи, хранимого в таблице cookies. Новый номер записи записывается в таблицу cookies и вызывается метод GenHTML. |
Startup |
информацию работника в первой записи таблицы. Startup создает новый идентификатор cookie - id - для пользователя и посылает его назад как скрытый вход в HTML . |
Поддержание сервера активным
Обычно, по каждому запросу от Web клиента, создается экземпляр сервер автоматизации, генерирующий HTML страницу и затем высвобождается с вызовом Release( ) в CallObject( ) в Foxisapi.cpp. Это означает, что полный Visual FoxPro runtime запускается и выгружается при каждом запросе.
Если сервер автоматизации ISAPI зарегистрирован, как Multi-Use и не вызывается Release(), тогда первый запрос запустит сервер, но последующие запросы будут использовать тот же самый экземпляр сервера, намного улучшая производительность. Код в Foxisapi.dll и методах Load, Cmd, DoSave, Startup и Skipit объекта ISForm управляет поддержкой одного активного экземпляра сервера.
Переменные в DLL
Задекларированы две переменных: pdispObj и pdispDoRelease. Когда сервер изначально создан, pdispObj представляет собой дескриптор диспетчера OLE объекта. Переменная pdispDoRelease устанавливается в то же самое значение, что и pdispObj и посылается по ссылке в качестве параметра методу ISForm сервера, который запрашивается Web браузером. Код в Visual FoxPro ISForm сервере автоматизации может изменить значение pdispDoRelease.
![]() |
---|
Для получения более подробной информации об этом образце смотрите комментарии в коде в ISForm и Foxisapi.cpp. |
Событие загрузки формы
Когда ISForm создан, код в событии Load создает две глобальные переменные, gpInstance и gpDisp. Когда сервер ISForm загружен первый раз, значение переменной gpInstance устанавливается в 1. Последующие экземпляры увеличивают значение этой переменной. Когда экземпляр высвобождается, значение переменной gpInstance уменьшается.
Методы точки входа
Когда через Foxisapi.dll вызывается метод (Cmd, DoSave, Skipit, or Startup) ISForm , .dll передает методу указатель диспетчера по ссылке в в качестве параметра.
Когда сервер запускается первый раз, счетчик экземпляров устанавливается в 1 и указатель диспетчера сохраняется в глобальной переменной. Затем в указателе сохраняется значение 0.
![]() | |
---|---|
IF m.gnInstance = 1 IF TYPE('pDisp') $ 'NI' gpDisp = m.pDisp pDisp = 0 ENDIF ENDIF |
В этой точке, две переменные указывают на одно и тоже значение указателя диспетчера: gpDisp в ISForm сервера автоматизации и pdispObj в Foxisapi.dll. Значение pdispDoRelease в .dll равно 0, как оно и было изменено в ISForm сервера автоматизации.
Следующие друг за другом вызовы сервера увеличивают счетчик экземлпяров, новый pdispObj генерируется в .dll, сохраняется в pdispDoRelease, и направляется по ссылке в запрашиваемый метод. Так как значение gnInstance не равно 1, значение переменной gpDisp не изменяется. Начиная с этой точки, gpDisp в сервере автоматизации хранит отличающееся значение от pdispObj и pdispDoRelease в .dll.
Высвобождение сервера
Для принужления высвобождения, pdispDoRelease не может содержать 0 и должно иметь значение, отличающееся от значения pdispObject. На высвобождение сервера оказывает влияние значение, посылаемое приведенным ниже текстом HTML страницы:
![]() | |
---|---|
<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd"> <INPUT NAME="Cmd" VALUE = "Reset"> <INPUT TYPE="submit" VALUE="Dos Command"> </FORM> |
Приведенный ниже код в методе cmd устанавливает значение pdispDoRelease для значения диспетчера первого экземпляра.
![]() | |
---|---|
CASE 'RESET'$upper(m.p1) m.pDisp= m.gpDisp |
Код в .dll будет теперь высвобождать текущий экземпляр и оригинальный экземпляры, который поддерживался в наличии для предотвращения загрузки Visual FoxPro каждый раз при вызыве сервера.
Посылка HTML клиенту
Метод GenHTML класса ISForm вызывается из каждого метода точки входа. HTML, возвращенный из методаGenHTML, возвращается Web браузеру через Internet Information Services.
Если параметр режима, посылаемый методу GenHTML не равен "FORM," то метод GenHTML просто ищет значение в таблице и посылает назад преформатированный HTML.
![]() | |
---|---|
IF m.mode != 'FORM' =SEEK(m.mode,'html') rv = html.html RETURN m.rv ENDIF |
Если параметр режима равен "FORM," код в GenHTML идентифицирует каждую метку и текстбокс на форме, сортирует их в порядке сверху вних и слева-направо, вычисляет Captions и ControlSources элементов управления и использует возможности Visual FoxPro сливать текст для конструирования подходящего текста HTML для отображения на форме.
Если вы добавили в форму дополнительные метки и текстбоксы, то они автоматически отображаются в сгенерированном HTML.
Создание и использование Cookies
В качестве Web сервера, это приложение может быть запрощено многократно разными клиентами и нам необходимо сохранять трэки состояний пользователей. В этом случае, мы сохраняем трек текущего номера записи для такого пользователя. Мы могли бы предоставить пользователю экран логина и использовать имя пользователя, как ключ для cookie, но вместо этого, мы генерируем значение cookie в методе MakeCookie и посылаем его в качестве скрытого значения в HTML, посылаемом назад пользователю. Каждый раз, когда пользователь выбирает другую запись, мы читаем значение cookie из строки HTTP, посылаемой .dll, ищем cookie в таблице Cookies, находим текущий номер записи и перемещаем указатель относительно этого номера.
В процессе управления cookie используются свойства и методы, перечисленные ниже:
-
Свойство Cookie
-
Метод GetCookie
-
Метод MakeCookie
-
Метод WriteCookieInfo
Обработка ошибок
Если произошла ошибка, код в событии Error класса ISForm вызывает метод GenHTML с параметром "ERROR." GenHTML читает предформатированный HTML текст для ошибок и возвращает его коду события Error. Код события Error замещает информацию об ошибке для соответствующих мест в HTML:
![]() | |
---|---|
LOCAL rv rv = THIS.GenHTML('ERROR') rv = strtran(m.rv,'%METHOD%',m.cMethod) rv = strtran(m.rv,'%ERRORNO%',STR(m.nError,4)) rv = strtran(m.rv,'%ERRORMSG%',Message(1)) rv = strtran(m.rv,'%LINENO%',STR(m.nLine,4)) THIS.ErrorHTML = m.rv |
Когда ErrorHTML что-то содержит, GenHTML посылает значение ErrorHTML назад, клиенту.
Таблицы, используемые в образце FoxIs
В дополнение к таблице employee, используемой для ввода данных и отображаения, образец FoxIs использует перечисленные ниже таблицы.
Таблица | Описание |
---|---|
HTML |
Хранит HTML текст посылаемый назад Web браузеру, как заголовок для вычислений FoxCMD и DosCMD илил в случае ошибки. |
Cookies |
Хранить трэки номеров записей для различных Web браузеров. Уникальное значение поля cookie посылается как скрытое значение в HTML тексте, посылаемое конкретному пользователю. |