2017-01-18 19 views
1

В C# можно написать обработчик событий следующим образом:обработчиков событий ActiveX в качестве HTA с помощью Javascript

var wdApp = new Microsoft.Office.Interop.Word.Application(); 
wdApp.DocumentBeforeSave += (Document doc, ref bool saveAsUI, ref bool cancel) => { 
    //do stuff here 
}; 

В VBA/VB6, я могу использовать статическую обработку событий:

Dim WithEvents wdApp As Word.Application 

Private Sub wdApp_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean) 
    'do stuff here 
End Sub 

Я бы предпочел для использования динамической обработки событий. Однако, в Javascript, даже при использовании статическога обработки с синтаксисом события описано here:

var wdApp = new ActiveXObject('Word.Application'); 
wdApp.Visible = true; 

function wdApp::Quit() { 
    window.alert('Quit'); 
}; 

это терпит неудачу:

0x800a138f - JavaScript runtime error: Object expected

Кроме того, статическая обработка событий является опцией в VBA/VB6, поскольку декларации может быть помечен Private. Однако в Javascript как переменная, так и обработчик должны быть объявлены в глобальной области.

Два вопроса:

  1. Как обрабатывать события автоматизации созданных объектов с Javascript в среде HTA? (Примечание: Я знаю, что это возможно в WSH с помощью префикса передается CreateObject и функцию с именем wdApp_Quit, но я искал решение ОМТ.)

  2. Как я могу сделать это без загрязняющих глобальный охват?


Существует старый вопрос here.

+0

У меня был взгляд, но я не могу заставить работать. В упомянутом решении WSH используется «ConnectObject», и я попытался использовать его в HTA с WScript.Shell, но он не работает. С 2009 года есть вопрос без ответа на ваш MSDN, поэтому похоже, что это будет невозможно. – Gordon

+0

Должно быть objectname :: eventname. https://msdn.microsoft.com/en-us/library/ms974564.aspx –

+0

Соединение событий, насколько я видел, зависит от объекта WScript, которого нет в mshta.exe host (который запускает HTAs). Однако mshta может вызывать объект javascript с узлом wscript.exe и получать доступ к объекту WScript. Будет ли такое решение для вас правильным, или это кажется слишком уродливым? –

ответ

1

Ошибка по-видимому, потому, что

  1. в Javascript function declarations are evaluated first, прежде чем переменная инициализируется. Это как если бы код был написан так:

    var wdApp; 
    function wdApp::Quit() { ... } 
    wdApp = new ActiveXObject('Word.Application'); 
    
  2. Анализатор Microsoft JScript интерпретирует специально под названием декларации в качестве инструкции, чтобы прикрепить функцию как обработчик события.

  3. Но в момент объявления обработчик не может быть прикреплен к объекту, на который ссылается , потому что wdApp в этом пункте по-прежнему undefined. Следовательно, ошибка.

Решение состоит в том, чтобы заставить объявление функции оцениваться после инициализации wdApp. Это может быть сделано в один из трех способов :

  1. Поскольку декларация функции водрузили только в пределах области видимости функции, оберните объявление функции в IIFE:

    var wdApp = new ActiveXObject('Word.Application'); 
    (function() { 
        function wdApp::Quit() { 
         //do stuff here 
        } 
    })(); 
    
  2. Создать декларация с помощью какой-то строки -> код механизма - eval, setTimeout, window.execScript или new Function:

    var wdApp = new ActiveXObject('Word.Application'); 
    eval('function wdApp::Quit() { ... }`); 
    
  3. Инициализировать переменную до текущего блока SCRIPT. Большинство примеров в Scripting Events статье сделать это, установив id свойство на некотором элементе до SCRIPT блока:

    <object progid="ordersystem.clsorder" id="myorder" events="true"/> 
    <script language="jscript"> 
        function myorder::onNew() { 
         WScript.Echo("new order received from myorder") 
        } 
    //... 
    

    , но это также может быть сделано с использованием нескольких SCRIPT блоков:

    <SCRIPT> 
        var wdApp = new ActiveXObject('Word.Application'); 
    </SCRIPT> 
    <SCRIPT> 
        function wdApp::Quit() { 
         //do stuff here 
        } 
    </SCRIPT> 
    

Что касается загрязнения глобального пространства имен, то только третий вариант требует, чтобы wdApp находился в глобальном масштабе mespace; другие два варианта можно обернуть в IIFE.


1. Технически, есть четвертый путь под IE и ОТЗА, но она включает в себя нестандартную HTML вместо нестандартного Javascript; Но его можно использовать, только если объект объявлен с использованием тега HTML OBJECT, а не с new ActiveXObject(...).

<script for="wdApp" event="Quit"> 
    //do stuff here 
</script> 
+0

так, :: работает только с eval или evalscript, так это? –

+0

@ EduardoPoço Или любая форма оценки строки - ['setTimeout'] (https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) или [' новая функция'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function). –

+0

@ EduardoPoço Кажется, что это также можно обернуть в IIFE. Обновлен мой ответ. –

0

Я не смог создать объект :: event синтаксис работы. Итак, я делегировал обработку событий вспомогательному скрипту, который следует.

caller.js файл:

var WordApp = WScript.CreateObject("Word.Application", "wd_"); 
WordApp.Visible = true; 

WScript.Sleep(20000); 

function wd_Quit() { //'object_event' works with js inside wscript.exe 
    WScript.Echo("word quit"); 
} 

Затем вызовите этот скрипт в файле HTA

main.hta файл:

<html> 
<script LANGUAGE="JScript"> 
    var shell = new ActiveXObject("WScript.Shell"); 
    shell.Run("caller.js"); 
</script> 
</html> 

Оба файла должны быть в той же папке. Запустите main.hta и вызывается код в caller.js, не загрязняя глобальное пространство имен HTA.

Этот пример предназначен для целей тестирования. Для сценария существует 20-секундный тайм-аут. По истечении этого времени оно прекратится, и события не будут обработаны.

Если это сработает, скажите мне, чтобы мы могли создать лучший способ связи с HTA (mshta.exe) с JS (wscript.exe). Существует возможность использовать «GetObject» из HTA для управления текстовым приложением (я сделал это один раз, но с VBScript), в то время как события обрабатываются JS-файлом.

+0

_I не мог сделать работу ** object :: event ** синтаксисом. Вы имеете в виду, не загрязняя глобальное пространство имен в ОМТ? Или вы имеете в виду, что это не работает вообще? Если последний, то какая версия Windows вы используете? 32-битный или 64-битный? –

+0

Официально этот синтаксис должен работать с JS под WScript, а также должен использоваться с 'eval' или несколькими элементами' SCRIPT' в '.wsf'. –

+0

Он выдает ошибку в строке. Я использую объект :: event, как если бы он не был частью синтаксиса. Не работает в wscript и ни mshta. Использование Win8.1x64 –