2009-04-28 20 views
7

Ich möchte einige Funktionalität hinzufügen bestimmte Aufrufe zu ActiveX-Objekt Methoden in Javascript hinzufügen.Erweitern eines ActiveXObject in Javascript

Normalerweise erstelle ich mein ActiveX-Objekt wie folgt: var tconn = neues ActiveXObject ("Tconnector");

Ich muss jedes Mal anmelden, wenn die offene Methode auf tconn aufgerufen wird und alle anderen Instanzen dieser ActiveX-Steuerelement.

Ich kann Tconn Prototyp nicht ändern, weil es einen nicht hat!

Ich denke, dass ich eine Dummy-ActiveXObject-Funktion erstellen kann, die ein Proxy-Objekt für Proxy-Aufrufe an die echte erstellt. Kannst du mir helfen, das zu tun?

Hinweis: Das Schreiben eines direkten Wrappers kommt nicht in Frage, da zu diesem activeX innerhalb der Anwendung bereits 1000 Aufrufe bestehen.

+1

Ich glaube nicht, dies möglich wird. Haben Sie eine Quelle für das Tconnetor? Können Sie die Binärdateien an die Clients weitergeben und/oder Ihre eigenen Binärdateien verteilen, wenn Sie sie nicht besitzen? – AnthonyWJones

+0

Ich habe nicht die Quelle, aber ich habe eine Lizenz, die es mir erlaubt, sie frei zu verteilen. Wie auch immer, warum ist das alles wichtig, wenn ich ein Proxy-Javascript-Objekt für Proxy-Aufrufe an das ActiveX-Objekt mache? – mkoryak

+0

@mkoryak: Ich habe den Code in meiner Antwort aufgeräumt/aktualisiert, und ich habe eine verknüpfende Antwort in Ihrer anderen Frage erstellt. – Tomalak

Antwort

12

Sie können ActiveXObject() überschreiben.

Dies bedeutet, dass Sie versuchen können, ein transparentes Proxy-Objekt um das tatsächliche Objekt zu erstellen und Methodenaufrufe anzuhängen. Dies würde bedeuten, dass Sie für jede Methode und Eigenschaft Ihres ActiveX-Objekts einen Proxy erstellen müssen, sofern Sie nicht absolut sicher sind, dass überhaupt kein Code eine bestimmte Methode oder Eigenschaft aufruft.

Ich habe einen kleinen Wrapper für das Objekt "MSXML2.XMLHTTP" gebaut. Es gibt wahrscheinlich alle Arten von Problemen, die in ausführen können, so nehmen, dass mit einem Körnchen Salz:

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); 
} 

Haftungsausschluss: Vor allem der Asynchron/onReadyStateChange Handhabung ist wahrscheinlich nicht richtig, und der Code kann andere Probleme als Gut. Wie gesagt, es ist nur eine Idee. Mit Vorsicht behandeln.

S.S .: Ein COM-Objekt unterscheidet nicht zwischen Groß- und Kleinschreibung, wenn es um Methoden- und Eigenschaftsnamen geht. Dieser Wrapper ist (wie alle JavaScript) abhängig von Groß- und Kleinschreibung. Zum Beispiel, wenn Ihr Code sowohl "Send()" und "send()" nennen passiert, werden Sie ein Skelett brauchen „Send()“ Methode in der Wrapper auch:

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

Woah, Weg, meine 100 Bounty Frage zu beantworten (http://stackoverflow.com/questions/756792/how-to-modify-activexobject-js-constructor). Ich mag es, Ihnen das Kopfgeld zu geben, da dies die nächste Antwort ist, die ich bekommen habe. Bitte gehen Sie dorthin und machen Sie einen Link zu Ihrer Antwort hier – mkoryak

+0

Das Wrapping des XMLHTTP-Objekts war eher ein Unfall. Ich hatte keine Ahnung von deiner anderen Frage. :-) – Tomalak

+0

+1 sehr schöne Lösung – andi

0

Das Problem hier ist, dass es scheint, dass wont IE erlauben Speicher des ursprünglichen activXObject-Konstruktors und gibt einen Stack-Überlauf (;-) beim Erstellen des ActualActiveXObject. es scheint, dass dies speziell für die ActivX ist, weil es funktioniert, wenn Sie dies mit anderen Javascript-Objekten tun.

2

Ein kleines Update für „Die Daten, die diesen Vorgang abzuschließen ist noch nicht verfügbar“ in IE6 - für Vollständigkeit, bevor Bevölkerung von reponse Eigenschaften warten:

für Ihren Wrapper
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

Vielen Dank. Mit Ihrer Hilfe konnte ich einen XML-Request-Detektor für IE und FF und den Rest erstellen.

Ich habe eine Version (kombiniert aus einem anderen Beispiel) hinzugefügt, die für FF, IE und den Rest der Bande arbeitet,

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; 
} 
} 
Verwandte Themen