Узнайте, открыта ли консоль Chrome


152

Я использую этот небольшой скрипт, чтобы узнать, открыт ли Firebug:

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

И это хорошо работает. Я полчаса искал способ определить, открыта ли встроенная консоль веб-разработчика Google Chrome, но я не смог найти никаких подсказок.

Этот:

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

не работает.

РЕДАКТИРОВАТЬ:

Так что, похоже, невозможно определить, открыта ли консоль Chrome. Но есть « хак », который работает, но с некоторыми недостатками:

  • не будет работать, когда консоль отстыкована
  • не будет работать, когда консоль открыта при загрузке страницы

Итак, я сейчас выберу «Неподписанный» ответ, но если кому-то в голову придет блестящая идея, он может все же ответить, и я изменю выбранный ответ! Благодарность!



Решение в ответе работает, но только в том случае, если консоль пристыкована. Также это не работает, если консоль уже открыта при загрузке страницы, в то время как скрипт Firebug не имеет этих проблем и, кажется, всегда работает. Но пока я могу жить с этим! Большое спасибо @pimvdb !! В любом случае я оставлю вопрос открытым, возможно, я найду способ, аналогичный сценарию Firebug, который всегда работает.
r0skar

Я пробовал такие вещи, как выдача ошибки и проверка, .messageизвлекается ли (что происходит, когда отладчик открыт, потому что вы видите сообщение), но, к сожалению, это также происходит, когда отладчик не открывается. Я хотел бы знать, как это сделать, если он существует ...
pimvdb

4
@Spudley Это не имеет отношения к вопросу, зачем мне это нужно, и я не хочу начинать объяснять. Я знаю, что нет способа предотвратить отладку some1, но я не это пытаюсь сделать. Я просто пытаюсь выяснить, открыта консоль или нет. Вот и все :)
r0skar

1
Метод JFYI console.profiles недавно был удален из консольного API src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Ответы:


106

requestAnimationFrame (конец 2019 г.)

Оставим эти предыдущие ответы здесь для исторического контекста. В настоящее время подход Мухаммада Умера работает в 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)

Поскольку исходного автора вопроса, похоже, больше нет, и это все еще принятый ответ, добавляем это решение для наглядности. Заслуга Антонин Хильдебранд «s комментарий на 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. Это решение больше не работает.

Спасибо Полу Айришу за указание на это решение из 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: невозможно прочитать свойство length of undefined в isInspectOpen ()
sandeep

2
Есть новый новый лучший способ (кредиты: @zswang): stackoverflow.com/questions/7798748/…
Вики Чиджвани

3
решение 'toString (2017)' не работает в Chrome
Ричард Чан

2
toString, похоже, исправлен в хроме. Редактировать. На самом деле это работает, если вы используете function() {}вместо регулярного выражения
Overcl9ck

1
@ Overcl9ck, ваше решение работало до последнего обновления Chrome 77. Можете ли вы указать нам верное направление для обходного пути?
Агустин Халлер

119

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 получат его идентификатор.

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 07

5
Кроме того, консоль «прочитает» элемент, как только консоль откроется, поэтому вы можете просто напечатать один раз и просто дождаться выполнения функции в получателе вместо установкиsetInterval
xpy

8
На основе этого открытия мне удалось найти менее навязчивый метод. DevTools вызывает toString () для функций при их выводе на консоль. Таким образом, можно напечатать пользовательский объект функции с переопределением метода toString (), возвращающим пустую строку. Кроме того, вы можете использовать строку форматирования консоли% c и установить цвет: прозрачный, чтобы потенциально печатный текст печатался как невидимый. Я использовал эту технику здесь: github.com/binaryage/cljs-devtools/blob/…
Антонин Хильдебранд

3
2017 год здесь. Chrome по-прежнему записывает данные на консоль, даже если вы ее не открываете. И твой хак больше не работает.
vothaison 04

2
Протестировано в firefox, не работает с элементом проверки (Q) и элемент проверки с помощью firebug
Асиф Ашраф

37

Очень надежный взлом

В основном установите геттер для свойства и зарегистрируйте его в консоли. Судя по всему, доступ к этой вещи возможен только тогда, когда консоль открыта.

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

5
Для чего throw new Error("Dev tools checker");? Потому что без него работает.
Legends

1
это похоже на спам консоли (при открытии)? который, как я предполагаю, начнет съедать значительное количество памяти через несколько дней :)
pythonator

1
Гениально! Этот метод можно изменить с помощью чего-то вроде console.log = function() {}и console.dir = function() {}.
Натан Гоингс,

Можно ли перенаправить страницу при открытии элемента Inspect Element. Скажите, если возможно. Спасибо
Химаншу Джайн

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 Я думаю, что ваш открытый инструмент разработчика закреплен, он не может обнаружить отдельное окно.
Mithril

К сожалению, он перестал работать для Chrome github.com/sindresorhus/devtools-detect/issues/40
laike9m

15

Я нашел способ узнать, открыта консоль Chrome или нет. Это все еще взлом, но он намного точнее и будет работать независимо от того, отстыкована консоль или нет.

В основном выполнение этого кода с закрытой консолью занимает около 100 микросекунд, а когда консоль открыта, требуется примерно вдвое больше ~ 200 микросекунд.

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

(1 миллисекунда = 1000 микросекунд)

Я уже писал об этом здесь .

Демо здесь .


Обновить:

@zswang нашел лучшее на данный момент решение - посмотрите его ответ


1
Это очень неправильное решение. Погуглите -> «Гоночная опасность». Медленнее или быстрее компьютер и ...?
18C

1
«Гоночная опасность» здесь не упоминается. При открытии консоли всегда наблюдается относительная медленность.
guya

1
Относительная медленность, но не всегда 100 или 200 мс. Таким образом, Race Hazard. Кстати. Если вы будете играть в игру в одно и то же время, это «решение» вернет ложноположительный результат.
18C

8

Если ваша цель - заглушить инструменты разработчика, попробуйте следующее (я нашел более сложную версию в месте, где JS-код был запутан, это очень раздражает):

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

Пользователь может в Chrome отключить прослушивание отладчика.
Джек Гиффин

@JackGiffin, До недавнего времени в Chrome была странная проблема. Деактивация точек останова не работала на 100%. Сейчас это исправлено, но в то время этот пост работал.
Натан Гоингс,

4

Я написал об этом сообщение в блоге: 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
Следующее решение «Race Hazard». Очень неправильно. Кстати. Команда "отладчик" может быть отключена.
18C

3

Есть хитрый способ проверить его на наличие расширений с разрешением «вкладки»:

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
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

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


Это не сработало. И ссылка на test onlineне работала.
Samuel

2

Инструменты разработчика Chrome - это просто часть библиотеки WebKit WebCore. Итак, этот вопрос относится к Safari, Chrome и любым другим потребителям WebCore.

Если решение существует, оно будет основано на разнице в DOM, когда веб-инспектор WebKit открыт и когда он закрыт. К сожалению, это своего рода проблема с курицей и яйцом, потому что мы не можем использовать инспектор для наблюдения за DOM, когда инспектор закрыт.

Что вы можете сделать, так это написать немного JavaScript, чтобы выгрузить все дерево DOM. Затем запустите его один раз, когда инспектор открыт, и один раз, когда инспектор закрыт. Любая разница в DOM, вероятно, является побочным эффектом веб-инспектора, и мы можем использовать его для проверки, проверяет ли пользователь или нет.

Эта ссылка - хорошее начало для сценария дампа DOM, но вы захотите сбросить весь DOMWindowобъект, а не только document.

Обновить:

Похоже, есть способ сделать это сейчас. Проверьте Chrome Inspector Detector


Chrome Inspector Detector больше не работает для google chrome, как упомянул разработчик
Анджело,

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 градусов, после чего размер экрана изменится.
Джек Гиффин

работает на chrome и ff not ie или edge по состоянию на 05.04.2019
SolidSnake 05

1

Подход Мухаммада Умера сработал для меня, и я использую 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. Если кто-то хочет расширить это, я хотел бы иметь возможность в какой-то момент остановить бесконечный цикл (поскольку я не использую это в каждом компоненте) и найти способ сохранить консоль в чистоте.


Можно ли перенаправить страницу при открытии элемента Inspect Element. Скажите, если возможно. Спасибо
Химаншу Джайн

0

Если вы разработчики, которые занимаются чем-то во время разработки. Проверьте это расширение Chrome. Это помогает определить, когда Chrome Devtoos открыт или закрыт.

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

Это расширение помогает разработчикам Javascript определять, когда Chrome Devtools открыт или закрыт на текущей странице. Когда Chrome Devtools закрывается / открывается, расширение вызывает событие с именем devtoolsStatusChanged в элементе 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
    }
});

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 вызывается немедленно, без открытия инспектора.

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

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

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


-1

используйте эту isDevToolsOpened()функцию пакета из пакета dev-tools-monitor, который работает должным образом во всех браузерах, кроме firefox.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.