В данной заметке, в качестве короткого введения, представлен прототип работы с Windows Script Host (WSH) из приложения 1С: Предприятие 7.7. Здесь же, представлены ссылки на некоторые, интересные на мой взгляд, разработки.
//--------------------------------------------------
// Запуск VBScript-сценариев в 1С:Предприятие 7.7
//--------------------------------------------------
// VBScript (и JScript)-сценарии можно выполнять в среде 1С: Предприятие 7.7,
// подключив Windows Script Host (WSH) в качестве ActivX-контрола:
Хост = СоздатьОбъект("MSScriptControl.ScriptControl");
// Установим язык интерпретатора:
Хост.Language = "VBScript";
//--------------------------------------------------
// Простой пример
//--------------------------------------------------
// Попробуем составить и вызвать на исполнение какую-нибудь простую
// процедуру или вычислить функцию. Например, ставшее хрестоматийным
// сообщение "Hello world"
// Загрузим исполняемый код:
Хост.AddCode( "Sub Say
| MsgBox ""Hello world""
|End Sub
|");
// Запуск загруженного кода на выполнение:
Хост.Modules("Global").CodeObject.Say();
//--------------------------------------------------
// Использование функций VBScript
//--------------------------------------------------
// Понятно, что выводить модальные окна может и само 1С: Предприятие 7.7,
// однако, с помощью VBScript можно производить некоторые вычисления, которые
// наша среда традиционно не поддерживает:
Хост.AddCode( "Function Pow(x,y)
| Pow = Exp(y*Log(x))
|End Function
|");
// Математическая функция вычисления степени числа:
Результат = Хост.Modules("Global").CodeObject.Pow(2, 8);
// VBScript возведение в степень также не поддерживает, зато поддерживает
// набор других функций, через который эту функцию можно выразить.
// Результат будет 255.999999999999 - почти то, что нужно...
Сообщить(Результат);
// А вот в javascript, кстати, такая функция есть:
Хост.Language = "JScript";
Хост.AddCode( "function pow(base, exponent) {
| return Math.pow(base, exponent);
|}
|");
Результат = Хост.Modules("Global").CodeObject.pow(2, 8);
// Результат будет уже "красивый"
Сообщить(Результат);
// Не каждый раз нам может понадобится датчик случайных чисел в 1С, но,
// вдруг захотим промоделировать какую-нибудь случайную величину. В конце
// -концов, в Excel-е же есть...
Хост.Language = "VBScript";
Хост.AddCode( "Function Random()
| Random = Rnd()
|End Function
|");
Результат = Хост.Modules("Global").CodeObject.Random();
Сообщить(Результат);
//--------------------------------------------------
// Построение "цепочки" инкапсуляций ActivX-контролов
//--------------------------------------------------
// Это когда в программной среде вызываем одну компоненту, а через
// нее - другую. Не слишком строгое определение, конечно, посмотрим, как
// это работает:
Текст = СоздатьОбъект("Текст");
Текст.ДобавитьСтроку("<html/>");
Текст.Записать(КаталогВременныхФайлов() + "test.html");
Хост.Language = "JScript";
// в WSH интерпретатор включили OLE-объект "DispHTMLDocument"...
ОбъектCRC = Хост.Eval(Шаблон("GetObject('[СтрЗаменить(КаталогВременныхФайлов(),""\"",""\\"")]test.html')"));
// ... и уже с этим объектом в среде 1С: Предприятие 7.7 обращаемся к
// его свойствам, вызываем методы...
ОбъектCRC.parentWindow.execScript("alert('hello world')", "javascript");
//--------------------------------------------------
// Работа с wsc-компонентами
//--------------------------------------------------
// Также можно создавать, подключать и работать с wsc-компонентами, создавая
// целые библиотеки функций. То есть, это тоже все есть и никуда не делось:
Текст = СоздатьОбъект("Текст");
Текст.ДобавитьСтроку("<?xml version='1.0' encoding='windows-1251'?>
|<component>
|<public>
| <method name='pow' />
|</public>
|<script language='javascript'>
| function pow(base, exponent) {
| return Math.pow(base, exponent);
| }
|</script>
|</component>
|");
// Сохранили библиотеку математических функций в файл
Текст.Записать(КаталогВременныхФайлов() + "test.wsc");
Хост.Language = "JScript";
// Подключили библиотеку...
ОбъектCRC = Хост.Eval(Шаблон("GetObject('script:[СтрЗаменить(КаталогВременныхФайлов(),""\"",""\\"")]test.wsc')"));
// ... и произвели какие-то вычисления с использованием ее функций
Результат = ОбъектCRC.pow(2, 8);
Сообщить(Результат);
//--------------------------------------------------
// Работа с классами VBScript
//--------------------------------------------------
// Не многие знают, но в VBScript есть возможность определять классы почти
// также, как и в любом объектно-ориентированном языке программирования. Там,
// правда нет полиморфизма и наследования, но в остальном, все вполне прилично:
Хост.Language = "VBScript";
Хост.AddCode( "Class MyClass
| Public Function MyFunction()
| MyFunction = ""Hello world""
| End Function
|End Class
|
|Dim MyObj
|Set MyObj = New MyClass
|");
// Получили инстанцированный в VBScript коде объект
Объект = Хост.Modules("Global").CodeObject.MyObj;
// Вызвали метод объекта
Результат = Объект.MyFunction();
Сообщить(Результат);
//--------------------------------------------------
// Работа с объектами VBScript
//--------------------------------------------------
// Помимо функций VBScript, мы можем обращаться также и к его объектам:
Хост.Language = "VBScript";
Хост.AddCode( "Function NetParams()
| Set NetParams = CreateObject(""WScript.Network"")
|End Function
|");
// Получили объект VBScript: "WScript.Network"...
СетевыеПараметры = Хост.Modules("Global").CodeObject.NetParams();
// ... и теперь можем обращаться к его методам:
Сообщить("Компьютер: " + СетевыеПараметры.ComputerName + ", Домен: " + СетевыеПараметры.UserDomain);
// Но не за это, конечно, стоит любить контрол "MSScriptControl.ScriptControl",
// ведь эту задачу можно решить минуя его, подключив объект в 1С напрямую:
СетевыеПараметры = СоздатьОбъект("WScript.Network");
Сообщить("Компьютер: " + СетевыеПараметры.ComputerName + ", Домен: " + СетевыеПараметры.UserDomain);
// ... или, вот еще пример:
oShell = СоздатьОбъект("WScript.Shell");
//oShell.SendKeys("%{F4}"); // - осторожно с этим, реально закрывает 1С: Предприяите 7.7 )))
// ... или, вот:
Темп = КаталогВременныхФайлов() + "sleep.vbs";
Текст = СоздатьОбъект("Текст");
// задержка на несколько мсек
Текст.ДобавитьСтроку("wscript.sleep 5000");
Текст.Записать(Темп);
cmdLine = "wscript.exe " + Темп;
WshShell = СоздатьОбъект("WScript.Shell");
время = _GetPerformanceCounter();
WshShell.Run(cmdLine, 0, -1);
Сообщить(_GetPerformanceCounter() - время); // - "врет" на 200 мс, кстати...
// ... сколько за возможность использовать конструкцию "for each..."
//--------------------------------------------------
// For Each
//--------------------------------------------------
// Цикл "for each..." не может быть реализован в 1С: Предприятие 7.7. Тем
// не менее, результатом некоторых Win-API функций могут быть неупорядоченные
// наборы данных, которые так или иначе нужно обрабатывать:
Хост.Language = "VBScript";
Хост.AddCode( "Function PIDs()
| PIDs = """"
| Set objService = GetObject(""WinMgmts:\\.\Root\CIMV2"")
| Set colProcess = objService.ExecQuery(""Select * from Win32_Process "" & _
| ""Where Name = '1cv7s.exe'"")
| For Each objProcess In colProcess
| PIDs = PIDs & "" "" & objProcess.ProcessId
| Next
| PIDs = LTrim(PIDs)
|End Function
|");
Результат = Хост.Modules("Global").CodeObject.PIDs();;
// Некоторая последовательность данных, которая уже может быть обработана
// в циклах "for..." или "while..."
Сообщить("""" + Результат + """");
//--------------------------------------------------
// Другие примеры
//--------------------------------------------------
// В заключение, хотелось бы привести интересные на мой взгляд, примеры
// других разработчиков. Первые два примера - это Получение PID исполняемого
// в данный момент процесса 1С и Вычисление SRC строки или файла я сам
// использую в работе. Где и зачем мне это понадобилось в бухгалтерской учетной
// системе - об этом позже... А вот третий, я глянул мельком и не запускал ни разу.
// Вообще, работать с компонентой "InetCtls.Inet.1", при необходимости, можно и
// в 1С: Предприятие 7.7 напрямую. Этот код здесь больше представлен как
// пример работы с VBScript-компонентами.