如何在IE兼容模式下调试注入的javascript代码?
How to debug injected javascript code in IE compatibility mode?
我需要向 IE 注入一些 Javascript 脚本,然后调用一些方法。
我尝试了以下简单的 C# 代码(Javascript 代码是从已知的 HTML 元素构建 xpath)。
string xpath = @"
(function(win) {
""use strict"";
var doc = win.document;
if (doc._xpath_installed) return;
doc._xpath_installed = true;
doc.createXPath = function (node, optimized) {
if (node.nodeType === Node.DOCUMENT_NODE) {
return '/';
}
var steps = [];
var contextNode = node;
while (contextNode) {
var step = _xPathValue(contextNode, optimized);
if (!step) {
break;
} // Error - bail out early.
steps.push(step);
if (step.optimized) {
break;
}
contextNode = contextNode.parentNode;
}
steps.reverse();
var stepvalues = [];
steps.forEach(function (step) {
stepvalues.push(_steptostring(step));
});
return (steps.length && steps[0].optimized ? '' : '/') + stepvalues.join('/');
};
var _xPathValue = function (node, optimized) {
var ownValue;
var ownIndex = _xPathIndex(node);
if (ownIndex === -1) {
return null;
} // Error.
switch (node.nodeType) {
case Node.ELEMENT_NODE:
if (optimized && node.getAttribute('id')) {
return _stepnew('//*[@id=""' + node.getAttribute('id') + '""]', true);
}
ownValue = node.localName;
break;
case Node.ATTRIBUTE_NODE:
ownValue = '@' + node.nodeName;
break;
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
ownValue = 'text()';
break;
case Node.PROCESSING_INSTRUCTION_NODE:
ownValue = 'processing-instruction()';
break;
case Node.COMMENT_NODE:
ownValue = 'comment()';
break;
case Node.DOCUMENT_NODE:
ownValue = '';
break;
default:
ownValue = '';
break;
}
if (ownIndex > 0) {
ownValue += '[' + ownIndex + ']';
}
return _stepnew(ownValue, node.nodeType === Node.DOCUMENT_NODE);
};
var _xPathIndex = function (node) {
// Returns -1 in case of error, 0 if no siblings matching the same expression,
// <XPath index among the same expression-matching sibling nodes> otherwise.
function areNodesSimilar(left, right) {
if (left === right) {
return true;
}
if (left.nodeType === Node.ELEMENT_NODE && right.nodeType === Node.ELEMENT_NODE) {
return left.localName === right.localName;
}
if (left.nodeType === right.nodeType) {
return true;
}
// XPath treats CDATA as text nodes.
var leftType = left.nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left.nodeType;
var rightType = right.nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : right.nodeType;
return leftType === rightType;
}
var siblings = node.parentNode ? node.parentNode.children : null;
if (!siblings) {
return 0;
} // Root node - no siblings.
var hasSameNamedElements;
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
hasSameNamedElements = true;
break;
}
}
if (!hasSameNamedElements) {
return 0;
}
var ownIndex = 1; // XPath indices start with 1.
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i])) {
if (siblings[i] === node) {
return ownIndex;
}
++ownIndex;
}
}
return -1;
};
var _stepnew = function(value, optimized) {
return {
value: value,
optimized: optimized || false
}
};
var _steptostring = function(step) {
return step[""value""];
};
})(window);
";
然后我尝试注入 xpath 字符串并调用一个方法,
// doc is the html document (type: mshtml.IHTMLDocument2)
// element is the html element (type: mshtml.IHTMLElement)
doc.parentWindow.execScript(xpath, "JScript");
object[] args = new object[2];
args[0] = element;
args[1] = 1;
object result = doc.GetType().InvokeMember("createXPath", BindingFlags.Instance | BindingFlags.InvokeMethod, null, doc, args);
它在 Internet Explorer 11 (Windows 10) 中工作正常。
但是,当我将网站添加到兼容性视图(设置-> 兼容性视图设置)时,InvokeMember 调用抛出异常“Exception from HRESULT: 0x80020101”,这意味着 Javascript代码。
我的问题是,在上述情况下,有没有办法调试这段 Javascript 代码?不调试,仅根据0x80020101信息,几乎不可能找到根本原因。
如果你的 JS 代码中有脚本错误,为什么不使用 console.log()
或 console.debug()
跟踪 client-side 代码的执行,以便你知道你的代码中发生了什么申请 ?
如果只想在Edge IE模式下调试代码,可以使用IEChooser打开Internet Explorer DevTools,如下:
- 在Windows中打开运行对话框。例如,按
Windows logo key
+ R
.
- 输入
%systemroot%\system32\f12\IEChooser.exe
,然后点击确定。
- 在 IEChooser 中,select IE 模式选项卡的条目。
更多的细节,你也可以参考这个文档:Open DevTools on a tab in IE mode.
我需要向 IE 注入一些 Javascript 脚本,然后调用一些方法。
我尝试了以下简单的 C# 代码(Javascript 代码是从已知的 HTML 元素构建 xpath)。
string xpath = @"
(function(win) {
""use strict"";
var doc = win.document;
if (doc._xpath_installed) return;
doc._xpath_installed = true;
doc.createXPath = function (node, optimized) {
if (node.nodeType === Node.DOCUMENT_NODE) {
return '/';
}
var steps = [];
var contextNode = node;
while (contextNode) {
var step = _xPathValue(contextNode, optimized);
if (!step) {
break;
} // Error - bail out early.
steps.push(step);
if (step.optimized) {
break;
}
contextNode = contextNode.parentNode;
}
steps.reverse();
var stepvalues = [];
steps.forEach(function (step) {
stepvalues.push(_steptostring(step));
});
return (steps.length && steps[0].optimized ? '' : '/') + stepvalues.join('/');
};
var _xPathValue = function (node, optimized) {
var ownValue;
var ownIndex = _xPathIndex(node);
if (ownIndex === -1) {
return null;
} // Error.
switch (node.nodeType) {
case Node.ELEMENT_NODE:
if (optimized && node.getAttribute('id')) {
return _stepnew('//*[@id=""' + node.getAttribute('id') + '""]', true);
}
ownValue = node.localName;
break;
case Node.ATTRIBUTE_NODE:
ownValue = '@' + node.nodeName;
break;
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
ownValue = 'text()';
break;
case Node.PROCESSING_INSTRUCTION_NODE:
ownValue = 'processing-instruction()';
break;
case Node.COMMENT_NODE:
ownValue = 'comment()';
break;
case Node.DOCUMENT_NODE:
ownValue = '';
break;
default:
ownValue = '';
break;
}
if (ownIndex > 0) {
ownValue += '[' + ownIndex + ']';
}
return _stepnew(ownValue, node.nodeType === Node.DOCUMENT_NODE);
};
var _xPathIndex = function (node) {
// Returns -1 in case of error, 0 if no siblings matching the same expression,
// <XPath index among the same expression-matching sibling nodes> otherwise.
function areNodesSimilar(left, right) {
if (left === right) {
return true;
}
if (left.nodeType === Node.ELEMENT_NODE && right.nodeType === Node.ELEMENT_NODE) {
return left.localName === right.localName;
}
if (left.nodeType === right.nodeType) {
return true;
}
// XPath treats CDATA as text nodes.
var leftType = left.nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left.nodeType;
var rightType = right.nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : right.nodeType;
return leftType === rightType;
}
var siblings = node.parentNode ? node.parentNode.children : null;
if (!siblings) {
return 0;
} // Root node - no siblings.
var hasSameNamedElements;
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
hasSameNamedElements = true;
break;
}
}
if (!hasSameNamedElements) {
return 0;
}
var ownIndex = 1; // XPath indices start with 1.
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i])) {
if (siblings[i] === node) {
return ownIndex;
}
++ownIndex;
}
}
return -1;
};
var _stepnew = function(value, optimized) {
return {
value: value,
optimized: optimized || false
}
};
var _steptostring = function(step) {
return step[""value""];
};
})(window);
";
然后我尝试注入 xpath 字符串并调用一个方法,
// doc is the html document (type: mshtml.IHTMLDocument2)
// element is the html element (type: mshtml.IHTMLElement)
doc.parentWindow.execScript(xpath, "JScript");
object[] args = new object[2];
args[0] = element;
args[1] = 1;
object result = doc.GetType().InvokeMember("createXPath", BindingFlags.Instance | BindingFlags.InvokeMethod, null, doc, args);
它在 Internet Explorer 11 (Windows 10) 中工作正常。
但是,当我将网站添加到兼容性视图(设置-> 兼容性视图设置)时,InvokeMember 调用抛出异常“Exception from HRESULT: 0x80020101”,这意味着 Javascript代码。
我的问题是,在上述情况下,有没有办法调试这段 Javascript 代码?不调试,仅根据0x80020101信息,几乎不可能找到根本原因。
如果你的 JS 代码中有脚本错误,为什么不使用 console.log()
或 console.debug()
跟踪 client-side 代码的执行,以便你知道你的代码中发生了什么申请 ?
如果只想在Edge IE模式下调试代码,可以使用IEChooser打开Internet Explorer DevTools,如下:
- 在Windows中打开运行对话框。例如,按
Windows logo key
+R
. - 输入
%systemroot%\system32\f12\IEChooser.exe
,然后点击确定。 - 在 IEChooser 中,select IE 模式选项卡的条目。
更多的细节,你也可以参考这个文档:Open DevTools on a tab in IE mode.