Dowiedz się, czy konsola Chrome jest otwarta

142

Używam tego małego skryptu, aby dowiedzieć się, czy Firebug jest otwarty:

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

I działa dobrze. Teraz szukałem przez pół godziny, aby znaleźć sposób na wykrycie, czy wbudowana internetowa konsola programisty Google Chrome jest otwarta, ale nie mogłem znaleźć żadnej wskazówki.

To:

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

nie działa.

EDYTOWAĆ:

Wygląda więc na to, że nie można wykryć, czy konsola Chrome jest otwarta. Jest jednak „ hack ”, który działa, ale ma kilka wad:

  • nie będzie działać, gdy konsola jest oddokowana
  • nie będzie działać, gdy konsola jest otwarta podczas ładowania strony

Więc na razie wybiorę odpowiedź Unsigned, ale jeśli ktoś1 wpadnie na genialny pomysł, może nadal odpowiedzieć, a ja zmieniam wybraną odpowiedź! Dzięki!

r0skar
źródło
Rozwiązanie w odpowiedzi wydaje się działać, jednak tylko wtedy, gdy konsola jest zadokowana. Nie działa również, jeśli konsola jest już otwarta podczas ładowania strony, podczas gdy skrypt Firebug nie ma tego problemu i wydaje się, że zawsze działa. Ale na razie mogę z tym żyć! Wielkie dzięki @pimvdb !! I tak pozostawiam to pytanie otwarte, aby być może znaleźć sposób podobny do skryptu Firebug, który zawsze działa.
r0skar
Próbowałem takich rzeczy, jak zgłaszanie błędu i sprawdzanie, czy .messagejest pobierany (co dzieje się, gdy debugger jest otwarty, ponieważ widzisz komunikat), ale niestety dzieje się tak również, gdy debugger nie jest otwarty. Chciałbym wiedzieć, jak to zrobić, jeśli istnieje ...
pimvdb
4
@Spudley To nie jest istotne dla pytania, dlaczego tego potrzebuję i nie chcę zaczynać wyjaśniać. Wiem, że nie ma sposobu, aby zapobiec debugowaniu some1, ale nie to próbuję zrobić. Po prostu próbuję znaleźć sposób, aby dowiedzieć się, czy konsola jest otwarta, czy nie. To wszystko :)
r0skar
1
Metoda JFYI console.profiles została niedawno usunięta z konsoli API src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Odpowiedzi:

97

requestAnimationFrame (koniec 2019 r.)

Pozostawiając te poprzednie odpowiedzi tutaj dla kontekstu historycznego. Obecnie podejście Muhammada Umera działa w Chrome 78, z dodatkową zaletą wykrywania zarówno zamkniętych, jak i otwartych wydarzeń.

funkcja toString (2019)

Kredyt dla Overcl9ck „s komentarz na tej odpowiedzi. Zastąpienie wyrażenia regularnego /./pustym obiektem funkcji nadal działa.

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

wyrażenie regularne toString (2017–2018)

Ponieważ oryginalnego pytającego nie ma już w pobliżu i nadal jest to akceptowana odpowiedź, dodanie tego rozwiązania w celu zwiększenia widoczności. Zasługa Antonin Hildebrand „s komentarz na zswang ” s odpowiedź . To rozwiązanie wykorzystuje fakt, że toString()nie jest wywoływane dla zarejestrowanych obiektów, chyba że konsola jest otwarta.

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)

Aktualizacja: console.profiles została usunięta z Chrome. To rozwiązanie już nie działa.

Podziękowania dla Paula Irisha za wskazanie tego rozwiązania z Discover DevTools przy użyciu profilera:

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)

Ta inna opcja może wykryć otwieranie zadokowanego inspektora po załadowaniu strony, ale nie będzie w stanie wykryć niezadokowanego inspektora lub jeśli inspektor był już otwarty podczas ładowania strony. Istnieje również pewien potencjał fałszywych trafień.

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

Bez podpisu
źródło
1
Getting TypeError: Cannot read property 'length' of undefined in isInspectOpen ()
sandeep
2
Jest nowe nowe najlepszym sposobem (ECTS: @zswang): stackoverflow.com/questions/7798748/...
Vicky Chijwani
3
rozwiązanie „toString (2017)” nie działa w chrome
Richard Chan
2
Wygląda na to, że toString zostało naprawione w chrome. Edytować. Właściwie to działa, jeśli używasz function() {}zamiast wyrażenia regularnego
Overcl9ck
1
@ Overcl9ck Twoje rozwiązanie działało do ostatniej aktualizacji Chrome 77. Czy możesz wskazać nam właściwy kierunek obejścia tego problemu?
Agustin Haller
118

Chrome 65+ (2018)

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

demo: https://jsbin.com/cecuzeb/edit?output (aktualizacja 2018-03-16)

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


Podczas drukowania „Elementu” narzędzia programistyczne Chrome otrzymają swój identyfikator

var checkStatus;

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

setInterval(function() {
    checkStatus = 'off';
    console.log(element);
    console.clear();
}, 1000);

Inna wersja (z komentarzy)

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

Wydrukuj zwykłą zmienną :

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);
zswang
źródło
3
Świetna odpowiedź. Jedna rzecz do dodania ... MDN twierdzi, że __defineGetter__jest przestarzały, więc zmieniłem na Object.defineProperty(element, 'id', {get:function() {checkStatus='on';}});... nadal działa.
denikov
5
Konsola również odczyta element zaraz po otwarciu konsoli, więc możesz po prostu wydrukować raz i po prostu poczekać, aż funkcja w getterze zostanie wykonana, zamiast ustawiaćsetInterval
xpy
8
Na podstawie tego odkrycia udało mi się znaleźć mniej inwazyjną metodę. DevTools wywołuje toString () w przypadku funkcji podczas drukowania ich na konsoli. Można więc wydrukować niestandardowy obiekt funkcji za pomocą metody toString (), przesłaniając zwracając pusty ciąg. Dodatkowo możesz użyć ciągu formatującego konsolę% c i ustawić kolor: przezroczysty, aby upewnić się, że potencjalnie wydrukowany tekst zostanie wydrukowany jako niewidoczny. Użyłem tej techniki tutaj: github.com/binaryage/cljs-devtools/blob/ ...
Antonin Hildebrand
3
Rok 2017 tutaj. Chrome nadal zapisuje rzeczy na konsoli bez jej otwierania. Twój hack już nie działa.
vothaison
2
Testowane na firefoxie nie działa z elementem inspekcyjnym (Q) i elementem inspekcyjnym za pomocą firebug
Asif Ashraf
28

Bardzo niezawodny hack

Zasadniczo ustaw getter we właściwości i zaloguj się w konsoli. Najwyraźniej rzecz jest dostępna tylko wtedy, gdy konsola jest otwarta.

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>

Muhammad Umer
źródło
Wersja Chrome 79 ✅
Legends
4
Do czego służy throw new Error("Dev tools checker");? Ponieważ działa bez niego.
Legends
wydaje się, że spamuje konsolę (po otwarciu)? który, jak zakładam, zacznie zjadać spore ilości pamięci po kilku dniach :)
pythonator
Jedyny sposób, który działa od 2020.7
laike9m
24

Stworzyłem devtools-detection, które wykrywa, kiedy DevTools jest otwarte:

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

Możesz także posłuchać wydarzenia:

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

Nie działa, gdy DevTools jest oddokowane. Jednak działa z Chrome / Safari / Firefox DevTools i Firebug.

Sindre Sorhus
źródło
@barbushin Myślę, że twoje otwarte devtool jest zadokowane, nie może wykryć oddzielnego okna.
Mithril
Niestety przestał działać dla Chrome github.com/sindresorhus/devtools-detect/issues/40
laike9m
15

Znalazłem sposób, aby sprawdzić, czy konsola Chrome jest otwarta, czy nie. To wciąż hack, ale jest o wiele dokładniejszy i będzie działał pod warunkiem, że konsola jest odłączona lub nie.

Zasadniczo uruchomienie tego kodu przy zamkniętej konsoli zajmuje około ~ 100 mikrosekund, a gdy konsola jest otwarta, zajmuje około dwa razy więcej ~ 200 mikrosekund.

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

(1 milisekunda = 1000 mikrosekund)

Więcej o tym pisałem tutaj .

Demo jest tutaj .


Aktualizacja:

@zswang znalazł aktualnie najlepsze rozwiązanie - sprawdź jego odpowiedź

guya
źródło
1
To bardzo złe rozwiązanie. Google it -> „Race Hazard”. Wolniejszy czy szybszy komputer i ...?
18C
1
„Race Hazard” nie jest tutaj powiązany. Po otwarciu konsoli zawsze występuje względne spowolnienie.
guya
1
Względna powolność, ale nie zawsze 100 lub 200 ms. Tak więc Race Hazard. Przy okazji. Jeśli zagrasz w grę w tym samym czasie, to „rozwiązanie” zwróci fałszywie dodatni wynik.
18C
8

Jeśli Twoim celem jest zablokowanie narzędzi programistycznych, spróbuj tego (znalazłem bardziej skomplikowaną wersję w miejscu, w którym kod JS został zaciemniony, jest to bardzo denerwujące):

setTimeout(function() {while (true) {eval("debugger");}}, 0);
Robert Moore
źródło
Użytkownik może w Chrome wyłączyć nasłuchiwanie debugera.
Jack Giffin
3

Istnieje trudny sposób sprawdzenia tego pod kątem rozszerzeń z uprawnieniem do kart:

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

Możesz również sprawdzić, czy jest otwarta dla Twojej strony:

chrome.tabs.query({
    url: 'chrome-devtools://*/*',
    title: '*example.com/your/page*'
}, function(tabs){ ... })
norlin
źródło
3

Napisałem o tym post na blogu: http://nepjua.org/check-if-browser-console-is-open/

Potrafi wykryć, czy jest zadokowany, czy oddokowany

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 ?")
    }
  });
});
nepjua
źródło
3
To miłe, ale spowoduje to, że strona przestanie istnieć i żadna wiadomość nie zostanie wyświetlona, ​​dopóki użytkownik nie kliknie przycisku wznowienia. Będzie to bardzo uciążliwe dla użytkownika.
guya
2
Kolejne rozwiązanie „Race Hazard”. Bardzo źle. BTW. Polecenie „debugger” można wyłączyć.
18C
3
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

setTimeout(()=>console.log(div),3000)
huiting Chen
źródło
To nie zadziałało. Link do test onlinenie działa.
Samuel
2

Narzędzia programistyczne Chrome są tak naprawdę tylko częścią biblioteki WebCore WebKit. To pytanie dotyczy przeglądarki Safari, Chrome i wszystkich innych użytkowników WebCore.

Jeśli rozwiązanie istnieje, będzie oparte na różnicy w DOM, kiedy inspektor sieci WebKit jest otwarty i kiedy jest zamknięty. Niestety jest to rodzaj problemu z kury i jaja, ponieważ nie możemy używać inspektora do obserwacji DOM, gdy inspektor jest zamknięty.

To, co możesz zrobić, to napisać trochę JavaScript, aby zrzucić całe drzewo DOM. Następnie uruchom go raz, gdy inspektor jest otwarty i raz, gdy inspektor jest zamknięty. Każda różnica w DOM jest prawdopodobnie efektem ubocznym inspektora sieci i być może uda nam się go użyć do sprawdzenia, czy użytkownik sprawdza, czy nie.

To łącze jest dobrym początkiem dla skryptu zrzutu DOM, ale będziesz chciał zrzucić cały DOMWindowobiekt, a nie tylko document.

Aktualizacja:

Wygląda na to, że można to teraz zrobić. Wypróbuj Chrome Inspector Detector

pepsi
źródło
Chrome Inspector Detector nie działa już w Google Chrome, o czym wspomniał programista
Angelo
1

Możesz także spróbować tego: 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);
});
Vladimir Ishenko
źródło
1
Nie działa dobrze. Jeśli użytkownik korzysta z urządzenia mobilnego, obróci swoje urządzenie o 90 stopni, a następnie zmieni rozmiar ekranu.
Jack Giffin
działa na chrome i ff not ie lub edge od 4/5/2019
SolidSnake
1

Podejście Muhammada Umera zadziałało dla mnie i używam Reacta, więc zdecydowałem się stworzyć rozwiązanie hooks:

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
}

UWAGA: Kiedy się z tym bawiłem, nie działało to najdłużej i nie mogłem zrozumieć, dlaczego. Usunąłem, console.dir(element);co jest krytyczne dla działania. Usuwam większość nieopisowych akcji konsoli, ponieważ zajmują one tylko miejsce i zwykle nie są potrzebne do funkcji, więc dlatego nie działało to dla mnie.

Aby z niego skorzystać:

import React from 'react'

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

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

Mam nadzieję, że pomoże to każdemu, kto używa React. Jeśli ktoś chciałby to rozwinąć, chciałbym w pewnym momencie zatrzymać nieskończoną pętlę (ponieważ nie używam tego w każdym komponencie) i znaleźć sposób na utrzymanie konsoli w czystości.

Luke Redmore
źródło
0

Jeśli jesteś programistą, który robi coś podczas programowania. Sprawdź to rozszerzenie do Chrome. Pomaga wykryć, kiedy Chrome Devtoos jest otwarty lub zamknięty.

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

To rozszerzenie pomaga programistom JavaScript wykrywać, kiedy Chrome Devtools jest otwarty lub zamknięty na bieżącej stronie. Gdy Chrome Devtools zamyka / otwiera się, rozszerzenie zgłosi zdarzenie o nazwie „devtoolsStatusChanged” w elemencie window.document.

Oto przykładowy kod:

 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
    }
});
Vothaison
źródło
0

Niektóre odpowiedzi przestaną działać w Chrome 65. Oto alternatywa ataku czasowego, która działa całkiem niezawodnie w Chrome i jest znacznie trudniejsza do złagodzenia niż toString()metoda. Niestety nie jest to takie niezawodne w Firefoksie.

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

});
Eli Grey
źródło
0

Jeśli chodzi o Chrome / 77.0.3865.75, wersja 2019 nie działa. toString wywołuje natychmiast, bez otwierania Inspektora.

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

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

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

korzhyk
źródło