使用Javascript

时间:2017-01-18 06:54:45

标签: events activex jscript hta activexobject

在C#中,我可以按如下方式编写事件处理程序:

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运行时错误:预期的对象

此外,静态事件处理是VBA / VB6中的一个选项,因为声明可以标记为Private。但是,在Javascript中,变量和处理程序都必须在全局范围内声明。

两个问题:

  1. 如何在HTA环境中使用Javascript处理自动化创建的对象事件? (注意:我知道在WSH中可以使用传递给CreateObject的前缀和一个名为wdApp_Quit的函数,但我正在寻找一个HTA解决方案。)

  2. 如何在不污染全局范围的情况下执行此操作?

  3. 有一个较旧的问题here

2 个答案:

答案 0 :(得分:1)

错误似乎是因为

    在初始化变量之前,在Javascript function declarations are evaluated first
  1. 。好像代码是这样写的:

    var wdApp;
    function wdApp::Quit() { ... }
    wdApp = new ActiveXObject('Word.Application');
    
  2. Microsoft JScript解析器将特别命名的声明解释为将该函数作为事件处理程序附加的指令。

  3. 但是在声明时,处理程序无法附加到wdApp引用的对象,因为此时wdApp仍为undefined。因此,错误。
  4. 解决方案是在初始化wdApp后强制评估函数声明。这可以通过三种方式之一 1

    完成
    1. 由于函数声明仅在函数范围内提升,因此将函数声明包装在IIFE中:

      var wdApp = new ActiveXObject('Word.Application');
      (function() {
          function wdApp::Quit() {
              //do stuff here
          }
      })();
      
    2. 使用某种字符串创建声明 - >代码机制 - evalsetTimeoutwindow.execScriptnew 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>
      
    4. 就污染全局命名空间而言,只有第三个变体需要wdApp在全局命名空间中;其他两个变种可以包裹在IIFE中。

      1。从技术上讲,在IE和HTA下有第四种方式,但它涉及非标准HTML而不是非标准Javascript;但只有在使用HTML OBJECT标记声明对象时才能使用它,而不能使用new ActiveXObject( ... )声明。功能

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

答案 1 :(得分:0)

我无法使 object :: 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)进行通信。有可能使用HTA中的“GetObject”来控制单词应用程序(我做了一次,但使用VBScript),而事件由JS文件处理。