了解Chrome控制台是否已打开

时间:2011-10-17 19:47:25

标签: javascript google-chrome firebug google-chrome-devtools

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

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

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

此:

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

不起作用。

编辑:

因此似乎无法检测Chrome控制台是否已打开。但是有一个“hack”可行,但有一些缺点:

  • 在控制台取消停靠时无效
  • 当控制台在页面加载时打开时,
  • 将无效。

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

20 个答案:

答案 0 :(得分:113)

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

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

答案 1 :(得分:69)

toString(2017-2018)

由于原始提问者似乎不再存在,这仍然是可接受的答案,因此添加此解决方案以提高可见性。在Antonin Hildebrand comment zswang上,answer Paul Irish点击。此解决方案利用了以下事实:除非控制台已打开,否则不会在已记录的对象上调用toString()

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

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

console.profiles(2013)

更新: console.profiles已从Chrome中移除。此解决方案不再有效。

感谢Discover DevTools使用探查器从{{3}}指出此解决方案:

function isInspectOpen()
{
    console.profile(); 
    console.profileEnd(); 
    if (console.clear) console.clear();
    return console.profiles.length > 0;
}

window.innerHeight(2011)

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

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

答案 2 :(得分:21)

我创建了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。

答案 3 :(得分:14)

我找到了一种方法来判断Chrome控制台是否已打开。 它仍然是一个黑客,但它更准确,并将工作天气控制台是否脱离。

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

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

(1毫秒= 1000微秒)

我已经写了更多关于here的文章。

演示是here


<强>更新

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

答案 4 :(得分:7)

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

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

答案 5 :(得分:5)

我找到了一种新方法:

var b=new Blob()
Object.defineProperty(b,'size',{get(){
    alert('The devtool was opened!')
}})
setTimeout(function(){console.log(b)},3000)

test online

答案 6 :(得分:3)

有一种棘手的方法可以通过&#39;标签&#39;来检查扩展名。权限:

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){ ... })

答案 7 :(得分: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 ?")
    }
  });
});

答案 8 :(得分:3)

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

使用console.profile、setInterval和toString函数

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

    setInterval(()=>{
        console.profile(devtools)
        console.profileEnd(devtools)
    }, 1000)

在 safari 中,它不起作用。

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

答案 9 :(得分:3)

非常可靠的黑客

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

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').innerHTML = checkStatus;
    requestAnimationFrame(check);
});

答案 10 :(得分:2)

Chrome开发人员工具实际上只是WebKit WebCore库的一部分。所以这个问题适用于Safari,Chrome和任何其他WebCore消费者。

如果存在解决方案,那么当WebKit Web检查器打开以及关闭时,它将基于DOM的差异。不幸的是,这是一种鸡和蛋的问题,因为我们不能在检查员关闭时使用检查员来观察DOM。

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

link是DOM转储脚本的良好开端,但您要转储整个DOMWindow对象,而不仅仅是document

<强>更新

现在看来有办法做到这一点。查看Chrome Inspector Detector

答案 11 :(得分:1)

这是我在 Chrome 和 Firefox 上使用的解决方案(今天是 2021 年 7 月 22 日):https://github.com/david-fong/detect-devtools-via-debugger-heartstop

我稍后会在 Safari 上对其进行测试。

复制自自述文件:

<块引用>

它打开一个带有轮询循环的网络工作者,该循环向主线程发送脉冲。每个脉冲是两条消息,它们之间有一个调试器语句,当在任何实现调试工作器的浏览器上打开 devtools 时,这将在封闭的消息之间产生异常延迟,并在打开 devtools 时启用始终调试。它不会阻塞主线程。

有关利弊以及谁应该和不应该使用它的更多详细信息在自述文件中。

答案 12 :(得分:1)

Muhammad Umer's approach为我工作,而我正在使用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的任何人有所帮助。如果有人想对此进行扩展,我希望能够在某个时候停止无限循环(因为我没有在每个组件中都使用此循环),并找到了一种保持控制台清洁的方法。

答案 13 :(得分: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);
});

答案 14 :(得分: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>

答案 15 :(得分:0)

此处的一些答案将停止在Chrome 65中运行。Here's a timing attack alternative在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);

});

答案 16 :(得分:0)

开发人员工具通常由专业开发人员使用键盘快捷键打开。您可以检测到这些组合键并捕获事件-或阻止打开面板。

[5.0, 4.8, 3.4, 4.9, 4.9]

打开开发人员工具的键盘快捷键:

答案 17 :(得分:0)

在每次打开控制台时强制显示彩色欢迎消息。

// Force a colorized welcome message
// each time the console is opened.

(() => { 
  w = new Function()
  w.toString = () => { (!this.z) ? console.log("%cWelcome to the console\n %cMaster password:\n %c window.password = ' ... ':", "color: white; font-size: 20px; background-color: blue", "color: white; font-size: 16px; background-color: red;margin 20px 0", "background: #222; color: #bada55") : this.z = true
}
  console.log('%c', w)
})()

答案 18 :(得分:0)

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

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

此扩展程序可帮助Javascript开发人员检测Chrome Devtools何时在当前页面上打开或关闭。 当Chrome Devtools关闭/打开时,该扩展程序将引发名为&#39; devtoolsStatusChanged&#39;在window.document元素上。

这是示例代码:

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

答案 19 :(得分:-1)

使用软件包dev-tools-monitor中的软件包Weekday功能 在除Firefox外的所有浏览器中都能正常工作。