找出Chrome控制台是否打开


141

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

if (window.console && window.console.firebug) {
    //is open
};

而且效果很好。现在,我正在搜索半小时,以找到一种方法来检测Google Chrome的内置Web开发人员控制台是否已打开,但找不到任何提示。

这个:

if (window.console && window.console.chrome) {
    //is open
};

不起作用。

编辑:

因此,似乎无法检测到Chrome控制台是否处于打开状态。但是有一个“ hack ”有效,但有一些缺点:

  • 控制台断开连接时将不起作用
  • 在页面加载中打开控制台时将不起作用

因此,我现在将选择Unsigned的答案,但是如果some1提出了一个绝妙的主意,欢迎他继续回答,我将更改选择的答案!谢谢!



答案中的解决方案似乎有效,但是仅在控制台已对接的情况下。如果控制台已在页面加载时打开,那么它也将不起作用,而Firebug脚本则不会出现此问题,并且似乎总是可以工作。但我现在可以忍受!非常感谢@pimvdb!无论如何,我都会保持开放的态度,也许可以找到一种类似于Firebug脚本的方法,该方法始终有效。
r0skar 2011年

我一直在尝试抛出错误并查看是否.message获取了错误(由于看到消息而在调试器打开时发生),但是不幸的是,在未打开调试器时也会发生这种情况。我想知道这个问题是否存在……
pimvdb 2011年

4
@Spudley这与为什么我需要它并且我不想开始解释的问题无关。我确实知道没有办法防止some1调试,但这不是我要尝试的方法。我只是想找出一种方法来知道控制台是否打开。多数民众赞成:)
r0skar 2011年

1
JFYI console.profiles方法最近已从控制台API中删除src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Answers:


97

requestAnimationFrame(2019年末)

这些先前的答案留在这里作为历史背景。目前,穆罕默德·乌默尔(Muhammad Umer)的方法可在Chrome 78上运行,并具有检测关闭事件和打开事件的附加优势。

函数toString(2019)

感谢Overcl9ck对这个答案的评论。/./用空函数对象替换正则表达式仍然有效。

var devtools = function() {};
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

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

正则表达式toString(2017-2018)

由于原始的问询者似乎不再存在,并且仍然是公认的答案,因此添加了此解决方案以提高可见性。幸得安东宁·希尔德布兰德评论zswang s'的答案。该解决方案利用了以下事实:toString()除非打开控制台,否则不会在记录的对象上调用该事实。

var devtools = /./;
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

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

console.profiles(2013)

更新: console.profiles已从Chrome中删除。该解决方案不再起作用。

感谢Paul Irish使用探查器从Discover DevTools指出了该解决方案:

function isInspectOpen() {
  console.profile();
  console.profileEnd();
  if (console.clear) {
    console.clear();
  }
  return console.profiles.length > 0;
}
function showIfInspectIsOpen() {
  alert(isInspectOpen());
}
<button onClick="showIfInspectIsOpen()">Is it open?</button>

window.innerHeight(2011)

此其他选项可以在页面加载之后检测到已停靠的检查器,但无法检测到未停靠的检查器,或者该检测器是否已在页面加载时打开。误报也有可能。

window.onresize = function() {
  if ((window.outerHeight - window.innerHeight) > 100) {
    alert('Docked inspector was opened');
  }
}


1
收到TypeError:无法读取isInspectOpen()中未定义的属性“长度”
sandeep

2
有一个新的新的最佳途径(学分:@zswang):stackoverflow.com/questions/7798748/...
维基Chijwani

3
'toString(2017)'的解决方案不适用于Chrome浏览器
Richard Chan

2
toString似乎已在chrome中修复。编辑。实际上,如果您使用a function() {}而不是正则表达式就可以工作
Overcl9ck

1
@ Overcl9ck您的解决方案在最新的Chrome 77更新之前一直有效。您能为我们指出正确的解决方法吗?
奥古斯丁·哈勒尔

118

Chrome 65+(2018)

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

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

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


打印“ Element”时,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);

另一个版本(来自评论)

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function () {
    /* TODO */
    alert('囧');
  }
});
console.log('%cHello', element);

打印一个常规变量:

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);

3
好答案。要添加的一件事... MDN说__defineGetter__不赞成使用,所以我改为Object.defineProperty(element, 'id', {get:function() {checkStatus='on';}});...仍在工作。
denikov

5
此外,控制台在控制台打开后将立即“读取”该元素,因此您只需打印一次,然后等待getter中的函数执行即可,而不是在setInterval
xpy

8
基于这一发现,我能够找到不太麻烦的方法。将工具打印到控制台时,DevTools会在函数上调用toString()。因此,可以使用覆盖返回空字符串的toString()方法来打印自定义函数对象。另外,您可以使用控制台格式字符串%c并设置color:transparent,以确保可能打印的文本显示为不可见。我在这里使用了这种技术:github.com/binaryage/cljs-devtools/blob/…–
Antonin Hildebrand

3
在这里的2017年。Chrome仍会在不打开控制台的情况下将内容写入控制台。而且您的骇客不再起作用。
vothaison

2
在firefox上进行测试不适用于带有Firebug的检查元素(Q)和检查元素
Asif Ashraf,2010年

27

非常可靠的破解

基本上在属性上设置一个吸气剂,并将其记录在控制台中。显然,只有在控制台打开时,事物才能被访问。

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

var checkStatus;

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);
  document.querySelector('#devtool-status').className  = checkStatus;
  requestAnimationFrame(check);
});
.on{
  color:limegreen;
}

.off{
  color:red;
}
<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>


Chrome版本79✅–
Legends

4
有什么throw new Error("Dev tools checker");用 因为没有它就可以工作。
传奇

这似乎向控制台发送了垃圾邮件(打开时)?我认为几天后就会开始消耗大量内存:)
pythonator

24

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

console.log('is DevTools open?', window.devtools.open);

您还可以听一个事件:

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

解除对接DevTools时,它不起作用。但是,可与Chrome / Safari / Firefox DevTools和Firebug一起使用。


@barbushin我认为您打开的devtool已停靠,无法检测到单独的窗口。
秘银

15

我找到了一种方法来判断Chrome控制台是否已打开。它仍然是一个hack,但是它的准确性更高,并且可以在控制台未插接的情况下正常工作。

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

console.log(1);
console.clear();

(1毫秒= 1000微秒)

我在这里写了更多有关它的内容。

演示在这里


更新:

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


1
这是非常错误的解决方案。谷歌它->“种族危害”。较慢或较快的计算机,...?
18C

1
“种族危险”与此处无关。打开控制台时,总是相对缓慢。
Guya '17

1
相对缓慢,但并不总是100或200ms。因此种族危险。顺便说一句。如果您要同时玩游戏,则此“解决方案”将返回假阳性结果。
18C

8

如果您的目标是阻塞开发人员工具,请尝试以下操作(我在混淆了JS代码的地方找到了一个更复杂的版本,这很烦人):

setTimeout(function() {while (true) {eval("debugger");}}, 0);

用户可以在Chrome中禁用侦听调试器。
杰克·吉芬

3

有一个棘手的方法来检查它是否具有'tabs'权限的扩展:

chrome.tabs.query({url:'chrome-devtools://*/*'}, function(tabs){
    if (tabs.length > 0){
        //devtools is open
    }
});

您也可以检查页面是否打开:

chrome.tabs.query({
    url: 'chrome-devtools://*/*',
    title: '*example.com/your/page*'
}, function(tabs){ ... })

3

我写了一篇关于此的博客文章: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 ?")
    }
  });
});

3
很好,但是它将使页面过时,并且直到用户单击“恢复”按钮时,才会显示任何消息。对用户而言,这将是非常麻烦的。
Guya'3

2
下一个“种族危害”解决方案。错了 顺便说一句。可以禁用“ debugger”命令。
18C

3
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

setTimeout(()=>console.log(div),3000)

没用 和的链接test online无效。
塞缪尔

2

Chrome开发人员工具实际上只是WebKit WebCore库的一部分。因此,此问题适用于Safari,Chrome和任何其他WebCore使用者。

如果存在解决方案,则将基于WebKit Web检查器打开和关闭时DOM中的差异。不幸的是,这是种鸡与蛋的问题,因为在关闭检查器时我们无法使用检查器来观察DOM。

您可能可以做的是编写一些JavaScript来转储整个DOM树。然后在检查器打开时运行一次,在检查器关闭时运行一次。DOM中的任何差异都可能是Web检查器的副作用,我们也许可以使用它来测试用户是否进行检查。

链接是DOM转储脚本的良好起点,但是您将要转储整个DOMWindow对象,而不仅仅是转储document

更新:

看起来现在有一种方法可以执行此操作。查看Chrome Inspector Detector


Chrome Inspector Detector不再适用于开发人员提到的Google chrome
Angelo

1

您也可以尝试以下方法:https : //github.com/sindresorhus/devtools-detect

// check if it's open
console.log('is DevTools open?', window.devtools.open);
// check it's orientation, null if not open
console.log('and DevTools orientation?', window.devtools.orientation);

// get notified when it's opened/closed or orientation changes
window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
    console.log('and DevTools orientation?', e.detail.orientation);
});

1
效果不好。如果用户在移动设备上,则将其设备旋转90度,然后屏幕将调整大小。
杰克·吉芬

自2019
SolidSnake

0

如果您是在开发过程中做事的开发人员。查看此Chrome扩展程序。它可帮助您检测何时打开或关闭Chrome Devtoos。

https://chrome.google.com/webstore/detail/devtools-status-detector/pmbbjdhohceladenbdjjoejcanjijoaa?authuser=1

此扩展程序可帮助Javascript开发人员检测Chrome Devtools在当前页面上何时打开或关闭。当Chrome Devtools关闭/打开时,扩展程序将在window.document元素上引发一个名为“ devtoolsStatusChanged”的事件。

这是示例代码:

 function addEventListener(el, eventName, handler) {
    if (el.addEventListener) {
        el.addEventListener(eventName, handler);
    } else {
        el.attachEvent('on' + eventName,
            function() {
                handler.call(el);
            });
    }
}


// Add an event listener.
addEventListener(document, 'devtoolsStatusChanged', function(e) {
    if (e.detail === 'OPENED') {
        // Your code when Devtools opens
    } else {
        // Your code when Devtools Closed
    }
});

0

这里的一些答案将在Chrome 65中停止工作。这是一种定时攻击替代方法,在Chrome中非常可靠地工作,并且比该toString()方法更难缓解。不幸的是,它在Firefox中并不是那么可靠。

addEventListener("load", () => {

var baseline_measurements = [];
var measurements = 20;
var warmup_runs = 3;

const status = document.documentElement.appendChild(document.createTextNode("DevTools are closed"));
const junk = document.documentElement.insertBefore(document.createElement("div"), document.body);
junk.style.display = "none";
const junk_filler = new Array(1000).join("junk");
const fill_junk = () => {
  var i = 10000;
  while (i--) {
    junk.appendChild(document.createTextNode(junk_filler));
  }
};
const measure = () => {
    if (measurements) {
    const baseline_start = performance.now();
    fill_junk();
    baseline_measurements.push(performance.now() - baseline_start);
    junk.textContent = "";
    measurements--;
    setTimeout(measure, 0);
  } else {
    baseline_measurements = baseline_measurements.slice(warmup_runs); // exclude unoptimized runs
    const baseline = baseline_measurements.reduce((sum, el) => sum + el, 0) / baseline_measurements.length;

    setInterval(() => {
      const start = performance.now();
      fill_junk();
      const time = performance.now() - start;
      // in actual usage you would also check document.hasFocus()
      // as background tabs are throttled and get false positives
      status.data = "DevTools are " + (time > 1.77 * baseline ? "open" : "closed");
      junk.textContent = "";
    }, 1000);
  }
};

setTimeout(measure, 300);

});

0

对于Chrome / 77 .0. 3865.75 , 2019年的版本不起作用。toString会立即调用而不会打开Inspector。

const resultEl = document.getElementById('result')
const detector = function () {}

detector.toString = function () {
	resultEl.innerText = 'Triggered'
}

console.log('%c', detector)
<div id="result">Not detected</div>


0

穆罕默德·乌默(Muhammad Umer)的方法对我有用,并且我正在使用React,所以我决定提供一个挂钩解决方案:

const useConsoleOpen = () => {
  const [consoleOpen, setConsoleOpen] = useState(true)

  useEffect(() => {
    var checkStatus;

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

    requestAnimationFrame(function check() {
      checkStatus = false;
      console.dir(element); //Don't delete this line!
      setConsoleOpen(checkStatus)
      requestAnimationFrame(check);
    });
  }, []);

  return consoleOpen
}

注意:当我弄乱它时,它在最长的时间内没有起作用,我也不知道为什么。我删除console.dir(element);了对它如何工作至关重要的内容。我删除了大多数非描述性的控制台操作,因为它们仅占用空间并且通常对该功能不是必需的,因此这就是为什么它对我不起作用的原因。

要使用它:

import React from 'react'

const App = () => {
  const consoleOpen = useConsoleOpen()

  return (
    <div className="App">
      <h1>{"Console is " + (consoleOpen ? "Open" : "Closed")}</h1>
    </div>
  );
}

我希望这对使用React的任何人有帮助。如果有人想对此进行扩展,我希望能够在某个时候停止无限循环(因为我没有在每个组件中都使用此功能),并找到了一种保持控制台清洁的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.