Дізнайтеся, чи відкрита консоль Chrome


142

Я використовую цей маленький сценарій, щоб дізнатися, чи Firebug відкритий:

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

І це добре працює. Зараз я шукав півгодини, щоб знайти спосіб виявити, чи відкрита вбудована консоль веб-розробника Google Chrome, але я не знайшов жодної підказки.

Це:

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

не працює.

Редагувати:

Тож здається, що виявити, чи відкрита консоль Chrome, неможливо. Але є " хак ", який працює, з деякими недоліками:

  • не буде працювати, коли консоль розблокована
  • не працюватиме, коли консоль відкрита при завантаженні сторінки

Отже, я зараз вибираю відповідь Непідписаний, але якщо some1 придумає геніальну ідею, він все одно може відповісти, і я поміняю обрану відповідь! Дякую!



Здається, рішення у відповіді працює, однак лише в тому випадку, якщо консоль підключена. Крім того, вона не працює, якщо консоль вже відкрита при завантаженні сторінки, тоді як у сценарію Firebug немає цих проблем і, здається, завжди працює. Але я можу з цим зараз жити! Велике спасибі @pimvdb !! Я завжди буду тримати відкрите питання, щоб, можливо, знайти спосіб, схожий на сценарій Firebug, який завжди працює.
r0skar

Я намагався такі речі, як закидання помилки і бачити, чи .messageє витягнутий (що відбувається, коли налагоджувач відкритий, оскільки ви бачите повідомлення), але, на жаль, це також відбувається, коли налагоджувач не відкритий. Я хотів би дізнатися про це, якщо він існує ...
pimvdb

4
@Spudley Це не стосується питання, навіщо мені це потрібно, і я не хочу починати пояснювати. Я знаю, що немає способу запобігти налагодженню some1, але це не те, що я намагаюся зробити. Я просто намагаюся з'ясувати спосіб дізнатися, відкрита чи консоль. Thats all :)
r0skar

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

Відповіді:


97

запитAramationFrame (кінець 2019 року)

Залишивши ці попередні відповіді тут для історичного контексту. В даний час підхід Мухаммада Умера працює на Chrome 78, з додатковою перевагою виявлення як близьких, так і відкритих подій.

функціяString (2019)

Кредит Overcl9ck «S прокоментувати цю відповідь. Заміна регулярного вираження /./порожнім функційним об'єктом все ще працює.

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

regex 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' undefined у isInspectOpen ()
sandeep

2
Там в нових нові кращі шляхи (кредити: @zswang): stackoverflow.com/questions/7798748 / ...
Vicky Chijwani

3
рішення «ToString (2017)» не працює в хромі
Річард Чен

2
toString, здається, зафіксовані в хромі. Редагувати. Насправді це працює, якщо ви використовуєте function() {}замість регулярного
виразу

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 отримають свій ідентифікатор

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 та встановити колір: прозорий, щоб переконатися, що потенційно надрукований текст друкується як невидимий. Я використав цю техніку тут: github.com/binaryage/cljs-devtools/blob/…
Антонін Хільдебранд

3
Рік 2017 тут. Chrome все ще записує речі на консолі, не відкриваючи їх. І твій хак уже не працює.
vothaison

2
Тестований на firefox не працює з Election Inspection (Q) та Inspect Element з firebug
Асиф Ашраф

28

Дуже надійний злом

В основному встановіть 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').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 ✅
Легенди

4
Для чого throw new Error("Dev tools checker");? Тому що це працює без нього.
Легенди

це здається спамом консолі (коли відкрито)? який я припускаю, що через кілька днів почне їсти значну кількість пам'яті :)
pythonator

Єдиний спосіб, який працює станом на 2020.7
laike9m

24

Я створив devtools-detete, який виявляє, коли 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 приєднаний, він не може виявити окреме вікно.
Мітріль

На жаль, він перестав працювати в Chrome github.com/sindresorhus/devtools-detect/isissue/40
laike9m

15

Я знайшов спосіб сказати, відкрита чи ні консоль Chrome. Це все-таки хак, але це набагато точніше і буде працювати за погодою, якщо консоль буде розблокована чи ні.

В основному запуск цього коду при закритій консолі займає близько 100 мікросекунд, а при відкритті консолі потрібно приблизно вдвічі більше 200 мікросекунд.

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

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

Про це я написав більше тут .

Демо тут .


Оновлення:

@zswang знайшов найкраще поточне рішення - ознайомтеся з його відповіддю


1
Це дуже неправильне рішення. Google it -> "Небезпека гонки". Повільніше або швидше комп'ютер і ...?
18C

1
"Небезпека гонки" тут не пов'язана. Завжди існує відносна повільність при відкритті консолі.
guya

1
Відносна повільність, але не завжди 100 або 200 мс. Таким чином, небезпека гонки. Btw. Якщо ви будете грати в гру одночасно, це "рішення" поверне помилковий позитивний результат.
18C

8

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

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

Користувач може в Chrome відключити прослуховування налагоджувача.
Джек Гіффін

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

Я написав про це запис у блозі: 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
Це приємно, але він затримає сторінку, і повідомлення не відображатиметься, поки користувач не натисне кнопку відновити. Це буде дуже настирливим для користувача.
гуя

2
Наступне рішення "Гонка небезпеки". Дуже неправильно. До речі. Команду "налагоджувач" можна відключити.
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 - це лише частина бібліотеки WebCore WebCore. Тож це питання стосується Safari, Chrome та будь-яких інших споживачів WebCore.

Якщо рішення існує, воно буде засноване на різниці в DOM, коли веб-інспектор WebKit відкритий і коли він закритий. На жаль, це певна проблема з куркою та яйцями, оскільки ми не можемо використовувати інспектора для спостереження за DOM, коли інспектор закритий.

Можливо, ви можете написати трохи JavaScript для скидання всього дерева DOM. Потім запустіть його один раз, коли інспектор відкритий, і один раз, коли інспектор закритий. Будь-яка різниця в DOM, ймовірно, є побічним ефектом веб-інспектора, і ми можемо використовувати його для тестування, перевіряє чи не користувач перевіряє.

Це посилання є гарним початком для сценарію демпінгу DOM, але ви хочете скинути весь DOMWindowоб’єкт, а не лишеdocument .

Оновлення:

Схоже, є спосіб зробити це зараз. Перевірте детектор інспектора Chrome


Детектор Chrome Inspector більше не працює для 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 градусів, тоді екран змінить розмір.
Джек Гіффін

працює з chrome та ff not ie or edge станом на 5.04.2019
SolidSnake

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. Якщо хтось хоче розширити цю проблему, я хотів би мати можливість зупинити нескінченний цикл в якийсь момент (оскільки я не використовую це в кожному компоненті) і знайти спосіб зберегти консоль чистою.


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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.