2009-04-28 30 views
7

我想添加一些功能来追踪某些对javascript中ActiveX对象方法的调用。在javascript中扩展ActiveXObject

我通常会这样创建我的activeX对象: var tconn = new ActiveXObject(“Tconnector”);

我需要记录每次打开方法在tconn和该activeX控件的所有其他实例上调用。

我不能修改tconn的原型,因为它没有!

我认为我可以创建一个虚拟ActiveXObject函数来创建一个代理对象来代理调用真实的代理对象。你能帮我做到吗?

注意:编写一个直接包装是没有问题的,因为在应用程序中已经有1000个对此ActiveX的调用。

+1

我不认为这会成为可能。 Tconnetor有源吗?如果您不拥有它,您可以将二进制文件重新分发给客户端和/或分发您自己的二进制文件吗? – AnthonyWJones 2009-04-28 13:39:38

+0

我没有来源,但我有一个许可证,允许我自由重新分配。无论哪种方式,为什么所有这些事情,如果我做一个代理JavaScript对象代理调用的ActiveX对象? – mkoryak 2009-04-28 13:47:25

回答

12

您实际上可以覆盖ActiveXObject()

这意味着您可以尝试围绕实际对象构建一个透明的代理对象,并挂钩方法调用。这意味着你必须围绕ActiveX对象的每个方法和属性构建一个代理,除非你确定没有任何代码调用特定的方法或属性。

我为"MSXML2.XMLHTTP"对象构建了一个小包装。可能有各种各样的,你可以遇到问题,所以采取与一粒盐:

var ActualActiveXObject = ActiveXObject; 

var ActiveXObject = function(progid) { 
    var ax = new ActualActiveXObject(progid); 

    if (progid.toLowerCase() == "msxml2.xmlhttp") { 
    var o = { 
     _ax: ax, 
     _status: "fake", 
     responseText: "", 
     responseXml: null, 
     readyState: 0, 
     status: 0, 
     statusText: 0, 
     onReadyStateChange: null 
     // add the other properties... 
    }; 
    o._onReadyStateChange = function() { 
     var self = o; 
     return function() { 
     self.readyState = self._ax.readyState; 
     self.responseText = self._ax.responseText; 
     self.responseXml = self._ax.responseXml; 
     self.status  = self._ax.status; 
     self.statusText = self._ax.statusText; 
     if (self.onReadyStateChange) self.onReadyStateChange(); 
     } 
    }(); 
    o.open = function(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword) { 
     varAsync = (varAsync !== false); 
     this._ax.onReadyStateChange = this._onReadyStateChange 
     return this._ax.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword); 
    }; 
    o.send = function(varBody) { 
     return this._ax.send(varBody); 
    }; 
    // add the other methods... 
    } 
    else { 
    var o = ax; 
    } 

    return o; 
} 

function Test() { 
    var r = new ActiveXObject('Msxml2.XMLHTTP'); 

    alert(r._status); // "fake" 

    r.onReadyStateChange = function() { alert(this.readyState); }; 
    r.open("GET", "z.xml"); 
    r.send(); 

    alert(r.responseText); 
} 

免责声明:特别是异步/ onreadystatechange的处理可能是不正确的,并且代码可能有其他一些问题好。正如我所说,这只是一个想法。小心轻放。

P.S .:一个COM对象在方法和属性名称时不区分大小写。这个包装(和所有的JavaScript一样)区分大小写。例如,如果你的代码恰好通话双方"Send()""send()",您将需要一个骨架“发送()”中的包装方法,以及:

o.Send = function() { return this.send.apply(this, arguments); }; 
0

这里的问题是,它似乎IE不会允许保存最初的activXObject构造函数,并且会在创建ActualActiveXObject时产生堆栈溢出(;-)。 似乎这对于ActivX来说是特别的,因为它在与其他JavaScript对象做同样的工作。

2

一点点修复“要完成这个操作的数据尚不可用”在IE6 - 效应初探性质的人口之前等待的完整性:

self.readyState = self._ax.readyState; 
if (self.readyState == 4) { 
    self.responseText = self._ax.responseText; 
    self.responseXml = self._ax.responseXml; 
    self.status  = self._ax.status; 
    self.statusText = self._ax.statusText; 
} 
if (self.onReadyStateChange) self.onReadyStateChange(); 
3

非常感谢您对您的包装。在您的帮助下,我可以为IE和FF创建一个xmlrequest检测器,其余部分。

我添加了一个版本(从另一个例子相结合),对于FF,IE和该团伙的其余产品,

if(window.XMLHttpRequest) 
{ 
var XMLHttpRequest = window.XMLHttpRequest; 

// mystery: for some reason, doing "var oldSend = XMLHttpRequest.prototype.send;" and 
// calling it at the end of "newSend" doesn't work... 
var startTracing = function() { 
    XMLHttpRequest.prototype.uniqueID = function() { 
     // each XMLHttpRequest gets assigned a unique ID and memorizes it 
     // in the "uniqueIDMemo" property 
     if (!this.uniqueIDMemo) { 
      this.uniqueIDMemo = Math.floor(Math.random() * 1000); 
     } 
     return this.uniqueIDMemo; 
    } 

    // backup original "open" function reference 
    XMLHttpRequest.prototype.oldOpen = XMLHttpRequest.prototype.open; 

    var newOpen = function(method, url, async, user, password) { 
     console.log("[" + this.uniqueID() + "] intercepted open (" + 
        method + " , " + 
        url + " , " + 
        async + " , " + 
        user + " , " + 
        password + ")"); 
     this.oldOpen(method, url, async, user, password); 
    } 

    XMLHttpRequest.prototype.open = newOpen; 

    // backup original "send" function reference 
    XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send; 

    var newSend = function(a) { 
     console.log("[" + this.uniqueID() + "] intercepted send (" + a + ")"); 
     var xhr = this; 
     var onload = function() { 
      console.log("[" + xhr.uniqueID() + "] intercepted load: " + 
        xhr.status + 
        " " + xhr.responseText); 
     }; 

     var onerror = function() { 
      console.log("[" + xhr.uniqueID() + "] intercepted error: " + 
        xhr.status); 
     }; 

     xhr.addEventListener("load", onload, false); 
     xhr.addEventListener("error", onerror, false); 

     this.oldSend(a); 
    } 
    XMLHttpRequest.prototype.send = newSend; 
} 


startTracing(); 
} 
else if (window.ActiveXObject) { 
var ActualActiveXObject = ActiveXObject; 

var ActiveXObject = function(progid) { 
    var ax = new ActualActiveXObject(progid); 

    if (progid.toLowerCase() == "msxml2.xmlhttp") { 

     var o = { 
      _ax: ax, 
      _status: "fake", 
      responseText: "", 
      responseXml: null, 
      readyState: 0, 
      status: 0, 
      statusText: 0, 
      onReadyStateChange: null 
     }; 
     o._onReadyStateChange = function() { 
      var self = o; 
      return function() { 
      self.readyState = self._ax.readyState; 
      if (self.readyState == 4) { 
       self.responseText = self._ax.responseText; 
       self.responseXml = self._ax.responseXml; 
       self.status  = self._ax.status; 
       self.statusText = self._ax.statusText; 
      } 
       if (self.onReadyStateChange) self.onReadyStateChange(); 
      } 
     }(); 
     o.open = function(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword) { 
      console.log("intercepted open (" + 
       bstrMethod + " , " + 
       bstrUrl + " , " + 
       varAsync + " , " + 
       bstrUser + " , " + 
       bstrPassword + ")"); 
      varAsync = (varAsync !== false); 
      this._ax.onReadyStateChange = this._onReadyStateChange 
      return this._ax.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword); 
     }; 
     o.send = function(varBody) { 
      return this._ax.send(varBody); 
     }; 
    } 
    else 
     var o = ax; 
    return o; 
} 
}