|
Принципы использования механизма MS Scripting в приложениях написанных на PowerBuilder |
|
|
Поскольку механизм Scripting требует, чтобы в скриптах, написанных, например, на VBScript, использовались только Scriptable COM-объекты, то минимальным требованием к таким объектам является экспорт IDispatch интерфейса. То есть, по сути, они должны являться OLE Automation серверами - предоставлять клиенту свою функциональность..
|
| |
|
Реализация хоста и парсера является довольно трудоемкой , но Microsoft предоставляет уже готовый хост, использующий стандартные парсеры vbscript.dll и jscript.dll. Предлагается он в виде OCX объекта с ProgID = MSScriptControl.ScriptControl. У него имеются функции для вычисления алгебраических выражений, запуска последовательности операторов, запуска собственно функций, с возможностью передачи параметров, передачи объектов в глобальное пространство имен скрипта. |
| |
|
Ипользование данной технологии рассматривается по следующему алгоритму:
|
| |
|
| Создается nonvisualobject (например, nv_scriptable), который будет автоматным сервером, и за методы которого будет дергать скрипт (написанный, например, на VBScript); |
| Создается wrapper, который будет уметь отображать состояния некоторых объектов ИС на созданный в пункте 1 автоматный сервер и обратно. |
|
| |
|
Далее рассматривается решение по обмену коллекциями между информационной системой (ИС) и скриптом
(написанным, например, на VBScript). Не требуется создавать промежуточного объекта nv_scriptable, поскольку у
механизма Scripting есть объект Dictionary. В примере коллекцией ИС является nonvisual объект appvar,
который содержит некоторый набор переменных, вычитанных из базы данных. |
| |
|
1. Создаем wrapper, который умеет инициализировать Scripting и отображать именованные переменные
в "Scripting.Dictionary".
| | |
|
| Функция инициализации init() |
|
string ls_script;
iole_dict = create OLEObject
long ll_result
ll_result = iole_dict.ConnectToNewObject('Scripting.Dictionary')
if ll_result < 0 then
uo_err.set_error(ls_script, &
"Невозможно подключиться к”+ & “серверу " + ls_server)
return -1
end if
iole_sm = create OLEObject
ll_result = iole_sm.ConnectToNewObject("MSScriptControl.ScriptControl")
if ll_result < 0 then
return -1
end if
// устанавливаем скрипт-язык
iole_sm.language = 'VBScript'
// добавляем в пространство имен срипт-хоста этот объект
iole_sm.AddObject("session", iole_dict)
// задаем используемые именованные переменные
pf_setvars()
return success
|
| Функция заполнения словаря pf_setvars() |
|
long i, ll_count
string ls_varnames[], ls_value
appvar.getallnames(ls_varnames)
ll_count = upperbound(ls_varnames)
for i = 1 to ll_count
ls_value = appvar.get(ls_varnames[i])
iole_dict.add(ls_varnames[i], ls_value)
next
return success
|
| Функция синхронизации коллекций pf_updatevars() |
|
long i, ll_count
string ls_varnames[], ls_value
// в зависимости от направления синхронизации
if bwrite then
// меняем значения именованных переменных
appvar.getallnames(ls_varnames)
ll_count = upperbound(ls_varnames)
for i = 1 to ll_count
ls_value = iole_dict.item(ls_varnames[i])
appvar.set(ls_varnames[i], ls_value)
next
else
// обновляем словарь
appvar.getallnames(ls_varnames)
ll_count = upperbound(ls_varnames)
for i = 1 to ll_count
ls_value = appvar.get(ls_varnames[i])
iole_dict.item(ls_varnames[i]) = ls_value
next
end if
return success
|
| Функция запуска скрипта runScript() |
|
// запишем коллекцию значений в объект Dictionary
pf_updatevars(false)
// funccode - текст скрипта, приведен ниже
//
iole_sm.AddCode(funccode)
string ls_result; ls_result = iole_sm.Run(“Main”)
// обновим коллекцию ИС значениями из объекта Dictionary
pf_updatevars(true)
return ls_result
|
| Пример скрипта |
|
Sub Main
MsgBox session.item("dbName")
End Sub
|
| |
PowerBuilder как OLE Automation Server
|
| |
|
По сути автоматным сервером является виртуальная машина pbvm60.dll,
таким образом любое приложение написанное на PowerBuilder может считаться автоматным in-proc сервером,
поскольку любое приложение работает на виртуальной машине PowerBuidler. Можно выделить два вида
(на самом деле их три) серверов, которые можно создавать на PowerBuilder:
|
| |
|
|
Именованный сервер. Такой сервер представляет собой одну динамическую библиотеку (.pbd или .dll), в
которой содержится набор объектов необходимых для выполнения какой-то функциональности.
Библиотека загружается виртуальной машиной и предоставляет клиенту интерфейс объекта (непременно nonvisualobject).
|
Ограничения: он не может использовать объекты из других библиотек (неизвестных виртуальной машине),
необходимо регистрировать его и его библиотеку типов (.reg и .tlb файлы создаются стандартной утилитой
из среды разработки PowerBuilder). Пример использования на VisualBasic:
|
Sub Test
Dim pbobject As Object
Set pbobject = CreateObject(“MyApp.nv_someobject”)
pbobject.uof_SayHello
End Sub
|
|
|
Сервер PowerBuilder.Application. Такой сервер представляет собой собственно виртуальную машину
PowerBuilder и позволяет использовать разные объекты из нескольких библиотек. Очень удобный вариант, за исключением того, что, как и в первом случае, используется собственная сессия PowerBuilder-а,
то есть прорваться между сессиями клиента написанном на PowerBuilder и сервера не представляется возможным.
Пример использования на VisualBasic: |
Sub Test
Dim pbobject As Object
Dim pbnv As Object
Set pbobject = CreateObject(“PowerBuilder.Application”)
pbobject.LibraryList = “e:\work\framework.pbd, e:\work\collection.pbd”
pbobject.MachineCode = False
Set pbnv = pbnv.CreateObject(“nv_collection_list”)
pbnv.append “a”, “alphabetical”
End Sub
|
|
|
| |
|
В последнем варианте большинство свойств и функций объектов, написанных на PowerBuilder, динамически преобразуются
в интерфейсы COM. Причем, очень приятно то, что динамическое создание объектов PowerBuilder в коде преобразуется в
создание COM объектов, поясню на примере:
|
| |
|
Метод CreateIterator принадлежит классу nv_collection_list : |
function nv_iterator_list CreateIterator()
// создаем итератор по коллекции
nv_iterator_list anv_iterator; anv_iterator = create nv_iterator_list
anv_iterator.setCollection(this)
anv_iterator.moveFirst()
return anv_iterator
end function
|
Тогда при использовании класса nv_collection_list как COM автоматного сервера, в скрипте клиента
также можно использовать nv_iterator_list как автоматный сервер: |
Sub Test
Dim pbobject As Object
Dim pbnv As Object
Dim iterator As Object
Set pbobject = CreateObject(“PowerBuilder.Application”)
pbobject.LibraryList = “e:\work\framework.pbd, e:\work\collection.pbd”
pbobject.MachineCode = False
Set pbnv = pbnv.CreateObject(“nv_collection_list”)
pbnv.append “a”, “alphabetical”
Set iterator = pbnv.CreateIterator
MsgBox iterator.getitem()
End Sub
|
Выполнение такого скрипта приведет к появлению на экране сообщения с текстом
«alphabetical». Главное, чтобы все используемые объекты находились в библиотеках
из списка LibraryList. |
|
| |
|
|
|