了解Chrome控制台是否已打开

r0s*_*kar 121 javascript firebug google-chrome google-chrome-devtools

我正在使用这个小脚本来查明Firebug是否已打开:

if (window.console && window.console.firebug) {
    //is open
};
Run Code Online (Sandbox Code Playgroud)

它运作良好.现在我正在寻找一种方法来检测Google Chrome的内置Web开发者控制台是否已打开,但我找不到任何提示.

这个:

if (window.console && window.console.chrome) {
    //is open
};
Run Code Online (Sandbox Code Playgroud)

不起作用.

编辑:

因此,似乎无法检测Chrome控制台是否已打开.但有一个" 黑客 "有效,但有一些缺点:

  • 控制台未对接时将无法工作
  • 控制台在页面加载时打开时无效

所以,我现在要选择Unsigned的答案,但如果有人提出了一个好主意,欢迎他仍然回答我改变所选答案!谢谢!

zsw*_*ang 117

Chrome 65+(2018)

r = /./
r.toString = function () {
    document.title = '1'
}
console.log('%c', r);
Run Code Online (Sandbox Code Playgroud)

演示:https://jsbin.com/cecuzeb/edit?output(更新于2018-03-16)

包:https://github.com/zswang/jdetects


打印"元素"时,Chrome开发者工具将获得其ID

var checkStatus;

var element = document.createElement('any');
element.__defineGetter__('id', function() {
    checkStatus = 'on';
});

setInterval(function() {
    checkStatus = 'off';
    console.log(element);
    console.clear();
}, 1000);
Run Code Online (Sandbox Code Playgroud)

另一个版本(来自评论)

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function () {
    /* TODO */
    alert('?');
  }
});
console.log('%cHello', element);
Run Code Online (Sandbox Code Playgroud)

打印常规变量:

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);
Run Code Online (Sandbox Code Playgroud)

  • 基于这一发现,我能够找到不太干扰的方法.当将它们打印到控制台时,DevTools会对函数调用toString().因此可以使用toString()方法覆盖返回空字符串来打印自定义函数对象.此外,您可以使用控制台格式化字符串%c并设置颜色:透明,以确保可能打印的文本打印为不可见.我这里使用这种技术:https://github.com/binaryage/cljs-devtools/blob/2e0615e7e037945db8ff39581de6cd367d9388d4/src/lib/devtools/util.cljs#L108 (8认同)
  • 控制台打开后,控制台也会"读取"元素,因此您只需打印一次,然后等待getter中的函数执行,而不是设置`setInterval` (5认同)
  • 很好的答案.有一点要补充...... MDN说`__ defineFetter__`已被弃用,所以我改为`Object.defineProperty(element,'id',{get:function(){checkStatus ='on';}});`...还在工作. (3认同)
  • 2017年这里.Chrome仍会在不打开它的情况下将内容写入控制台.你的黑客不再工作了. (3认同)
  • 在firefox上测试不适用于检查元素(Q)和使用firebug检查元素 (2认同)
  • Chrome 金丝雀现在阻止第一种方法工作 (https://github.com/zswang/jdetects/issues/3) (2认同)

Uns*_*ned 81

toString(2017-2018)

由于原始提问者似乎不再存在,这仍然是可接受的答案,因此添加此解决方案以提高可见性.幸得安东宁·希尔德布兰德评论zswang s'的答案././除非控制台是打开的,否则此解决方案利用了未在已记录对象上调用的事实.

var devtools = function(){};
devtools.toString = function() {
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened
Run Code Online (Sandbox Code Playgroud)

console.profiles(2013)

更新: toString()已从Chrome中删除.此解决方案不再有效.

感谢Paul Irish使用Profiler 从Discover DevTools指出这个解决方案:

var devtools = /./;
devtools.toString = function() {
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened
Run Code Online (Sandbox Code Playgroud)

window.innerHeight(2011)

这个其他选项可以在页面加载检测正在打开的停靠检查器,但是无法检测到未停靠的检查器,或者检查器是否已在页面加载时打开.误报也有一些可能性.

function isInspectOpen()
{
    console.profile(); 
    console.profileEnd(); 
    if (console.clear) console.clear();
    return console.profiles.length > 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 'toString(2017)'的解决方案在chrome中不起作用 (3认同)
  • 获取类型错误:无法读取 isInspectOpen() 中未定义的属性“长度” (2认同)
  • 有一种新的最佳方法(学分:@zswang):http://stackoverflow.com/questions/7798748/find-out-whether-chrome-console-is-open/30638226#30638226 (2认同)
  • toString似乎已在chrome中修复。编辑。实际上,如果您使用`function(){}`而不是正则表达式,则可以使用 (2认同)
  • 已使用 Chrome v80.0.3987.149 确认 - 仍然无法正常工作。 (2认同)

Muh*_*mer 47

非常可靠的黑客

基本上在属性上设置一个 getter 并将其记录在控制台中。显然,只有在控制台打开时才能访问该内容。

https://jsfiddle.net/gcdfs3oo/44/

var checkStatus;
var indicator = document.querySelector('#devtool-status');

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function() {
    checkStatus='on';
    throw new Error("Dev tools checker");
  }
});

requestAnimationFrame(function check() {
  checkStatus = 'off';
  console.dir(element);
  indicator.className  = checkStatus;
  requestAnimationFrame(check);
});
Run Code Online (Sandbox Code Playgroud)
.on{
  color:limegreen;
}

.off{
  color:red;
}
Run Code Online (Sandbox Code Playgroud)
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.css" integrity="sha256-DVK12s61Wqwmj3XI0zZ9MFFmnNH8puF/eRHTB4ftKwk=" crossorigin="anonymous" />

<p>
  <ul>
    <li>
      dev toolbar open: icon is <span class="on">green</span>
    </li>
    <li>
      dev toolbar closed: icon is <span class="off">red</span>
    </li>
  </ul>
</p>
<div id="devtool-status"><i class="fas fa-7x fa-power-off"></i></div>
<br/>
<p><b>Now press F12 to see if this works for your browser!</b></p>
Run Code Online (Sandbox Code Playgroud)

  • 这在 chrome 90(稳定)中不再有效 (7认同)
  • ` throw new Error("Dev tools checker");` 是做什么用的?因为没有它它也能工作。 (6认同)
  • Chrome Canary 89.0.4373.0 不再有效 ❎ (5认同)
  • 这似乎向控制台发送垃圾邮件(打开时)?我认为几天后它将开始消耗大量内存:) (2认同)

Sin*_*hus 21

我创建了devtools-detect,可以检测DevTools何时打开:

console.log('is DevTools open?', window.devtools.open);
Run Code Online (Sandbox Code Playgroud)

您还可以收听活动:

window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
});
Run Code Online (Sandbox Code Playgroud)

当DevTools未对接时它不起作用.但是,适用于Chrome/Safari/Firefox DevTools和Firebug.

  • 遗憾的是它不再适用于 Chrome https://github.com/sindresorhus/devtools-detect/issues/40 (2认同)

mol*_*arg 21

console.log(Object.defineProperties(new Error, {
  message: {get() {alert('Chrome/Firefox')}},
  toString: {value() {(new Error).stack.includes('toString@')&&alert('Safari')}}
}));
Run Code Online (Sandbox Code Playgroud)

演示: https: //jsbin.com/cateqeyono/edit?html,输出


guy*_*uya 15

我找到了一种方法来判断Chrome控制台是否已打开.它仍然是一个黑客,但它的方式更准确,并将工作天气控制台是否取消对接.

基本上在控制台关闭的情况下运行此代码需要约100微秒,而控制台打开时需要大约两倍~200微秒.

console.log(1);
console.clear();
Run Code Online (Sandbox Code Playgroud)

(1毫秒= 1000微秒)

我在这里写了更多关于它的文章.

演示就在这里.


更新:

@zswang找到了目前最好的解决方案 - 看看他的答案

  • 这是非常错误的解决方案。谷歌它 - &gt;“种族危险”。较慢或较快的计算机以及...? (4认同)
  • “种族危险”与此无关。打开控制台时总是相对缓慢。 (2认同)
  • 相对较慢,但并不总是 100 或 200 毫秒。因此,种族危险。顺便提一句。如果您同时玩游戏,此“解决方案”将返回误报结果。 (2认同)

sta*_*all 15

似乎有一些常见的解决方案:

  • 依赖于在开发工具出现时检测屏幕大小的调整(当开发工具/控制台作为单独的窗口打开时,这不起作用)
  • 拦截某些可以调出开发工具/控制台的用户操作,例如右键菜单、F12、Ctrl+Shift+C 等。这不能涵盖页面无法检测到的浏览器镶边中的 UI 机制。
  • 将某些内容记录到控制台并依赖浏览器特定的行为来进行懒惰、精美的打印。从历史上看,这些似乎不太可靠,但它们很好而且简单。如果您希望它们在同一浏览会话中重复工作,您可能必须接受某种程度的控制台垃圾邮件。
  • 对语句使用计时启发法debugger棘手的部分是找到一种方法,使计时器不会被事件循环队列中长时间运行的任务弄乱,并且调试器语句会暂停其运行的线程的执行。还有一个挑战是用户可以根据具体情况或禁用全部来禁用常规调试器语句。

下面是我针对该debugger方法的具体问题的解决方案。IE。当主线程在启发式计时器之间运行长任务时,避免误报,避免debugger语句阻塞主线程,并防止禁用调试器语句。注意:我认为没有办法阻止用户禁用所有调试器断点,这可能是最好的方法。

怎么运行的

当开发工具打开且线程遇到调试语句时,Chrome 浏览器会进入调试状态。

  1. 主线程向 webworker 线程发送消息。
  2. 工作线程以打开的心跳进行回复。
  3. 主线程通过启动计时器来响应关闭心跳。
  4. 工作线程的消息处理程序遇到调试器语句(可以选择包含在eval语句中以防止用户禁用它)。
  5. 如果 devtools 关闭,worker 将立即向主线程发送确认,主线程将得出 devtools 已关闭的结论。
  6. 如果打开 devtools,worker将进入调试会话,主线程会注意到 Worker 没有足够快地响应,从而得出调试器必须打开的结论。主线程不会工作线程的调试会话阻塞,但它的超时响应将被事件队列中主线程中位于其前面的任何繁重处理所阻塞。

我已经在 GitHub 上发布了一个参考实现(由我编写),并在此处发布了一个演示

优点

  • 与屏幕尺寸更改检测方法不同,当控制台位于单独的窗口中时,此方法有效。
  • 与用户操作拦截方法不同,无论用户操作如何调出控制台,这种方法都有效。
  • 与其他方法不同console.log,这可以适用于控制台的多个打开-关闭,而不会向控制台发送大量消息。
  • 与基本的计时器调试器方法不同,检测不应因繁忙的线程(主线程或其他工作线程)而触发误报,调试器语句位于工作线程而不是主线程中,因此主线程不会被阻塞, eval-debugger 语句可防止禁用该特定调试器语句。

缺点

  • 用户可以禁用所有断点,这将禁用这种检测方法。
  • eval 包装的调试器语句在通过内容安全策略禁用 eval 的站点上不起作用,在这种情况下只能使用常规调试器语句。


Rob*_*ore 7

如果你的目标是堵塞开发人员工具,试试这个(我在JS代码被混淆的地方找到了一个更复杂的版本,这非常烦人):

setTimeout(function() {while (true) {eval("debugger");}}, 0);
Run Code Online (Sandbox Code Playgroud)


nep*_*jua 5

我写了一篇关于这个的博客文章:http : //nepjua.org/check-if-browser-console-is-open/

它可以检测它是停靠还是未停靠

function isConsoleOpen() {  
  var startTime = new Date();
  debugger;
  var endTime = new Date();

  return endTime - startTime > 100;
}

$(function() {
  $(window).resize(function() {
    if(isConsoleOpen()) {
        alert("You're one sneaky dude, aren't you ?")
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 下一个“种族危险”解决方案。非常错误。顺便提一句。可以禁用“调试器”命令。 (4认同)
  • 这很好,但是,它会使页面陈旧,并且在用户单击恢复按钮之前不会显示任何消息。这对用户来说是非常具有侵入性的。 (3认同)

小智 5

我发现新方法在 Chrome 89 上有效

使用 console.profile、setInterval 和函数 toString

    var devtools = function() {};
    devtools.toString = function() {
        alert('NOPE!!')
        return '-'
    }

    setInterval(()=>{
        console.profile(devtools)
        console.profileEnd(devtools)
    }, 1000)
Run Code Online (Sandbox Code Playgroud)

在 safari 中,它不起作用。

在 chrome 89 以下,我无法检查它是否有效。