Запуск VBScript-сценариев в 1С: Предприятие 7.7


В данной заметке, в качестве короткого введения, представлен прототип работы с 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-компонентами.