Принципы использования механизма 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.
     Evgeny Savitsky © 2002-2003
    Hosted by uCoz